> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ctrl-hub.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a report

> Schedule a saved query's results for delivery.

The report runs as the caller: every run executes with the creator's real materialised
grants, so a report can never surface rows its owner could not see for themselves. The
query must exist and the caller must be able to view it.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v3/reports
openapi: 3.1.0
info:
  contact:
    email: support@ctrl-hub.com
    name: Ctrl Hub
    url: https://www.ctrl-hub.com
  description: >
    Ctrl Hub is the all-in-one platform for high-risk industries like utilities,
    construction, infrastructure, and renewables. We help teams manage
    everything from risk assessments and HAVS exposure to vehicle and equipment
    checks, with a guaranteed minimum of 200% ROI.
  license:
    name: MIT License
    url: https://opensource.org/licenses/MIT
  summary: An API for managing your compliance and risk posture
  termsOfService: https://www.ctrl-hub.com/terms-conditions
  title: Ctrl Hub
  version: 1.0.0
servers:
  - description: Production
    url: https://api.ctrl-hub.com
  - description: Staging
    url: https://api.ctrl-hub.dev
  - description: Development
    url: https://api.ctrl-hub.run
security: []
tags:
  - description: |
      Actions are follow-ups assigned to users and teams, produced manually or
      by domain producers such as the data-capture workflow runner.
    name: Actions
  - description: |
      Audit events are the events that are logged by the system.
    name: Audit Events
  - description: |
      View the platform's health and availability.
    name: Status
  - description: >
      User-owned dashboards composed of cards on a fixed-slot bento layout.
      Cards come from a per-domain registry; the API stores their config as
      opaque JSON.
    name: Dashboards
  - description: >
      A record of documents the platform generated and handed over, retained as
      evidence of what

      was issued. `subject_type` says what kind of records an export covers, and
      it is what decides

      how the request is authorised: there is no export permission of its own,
      so if you can see the

      records you can export them.
    name: Exports
  - description: >
      Scheduled delivery of a saved query's results, as a CSV attachment or a
      summary email. Every run is retained with the file it sent, so what a
      recipient received stays retrievable. A report runs as the person who
      created it, under their own access.
    name: Reports
  - description: |
      Manage appointments for work to be carried out with your customers
    name: Customer Appointments
  - description: |
      Manage interactions you have with your customers
    name: Customer Interactions
  - description: |
      Manage accounts for your customers
    name: Customer Accounts and Contacts
  - description: |
      Qualifications are the skills and knowledge that an organisation requires.
    name: Qualifications
  - description: |
      Workflows allow you to automate your processes.
    name: Workflows
  - description: |
      Manage documents
    name: Documents
  - description: |
      Manage documents
    name: Folders
  - description: |
      Manage documents
    name: Document Reviews
  - description: |
      Manage feature configurations for an organisation.
    name: Feature Configurations
  - description: |
      Equipment are the physical assets that an organisation manages.
    name: Equipment
  - description: |
      The central cost register: time-versioned rate codes for material, labour,
      contractor and miscellaneous spend, used to cost work against the job
      hierarchy.
    name: Costs
  - description: >
      Locations are places an organisation manages, optionally classified by a
      location type.
    name: Locations
  - description: |
      Manage your forms and their schemas
    name: Forms, Schemas and Categories
  - description: |
      Create and view form submissions
    name: Submissions
  - description: |
      View the roles available in the system.
    name: IAM Roles
  - description: >
      IAM role groups can be assigned to principals to manage authorisation
      centrally.
    name: IAM Role Groups
  - description: |
      Manage service accounts which can access the API programmatically.
    name: Service Accounts
  - description: |
      Manage bridges between organisations.
    name: Bridges
  - description: |
      Manage settings for an organisation.
    name: Settings
  - description: |
      Manage teams within an organisation.
    name: Teams
  - description: |
      Manage job roles within an organisation.
    name: Job Roles
  - description: |
      Manage users and accounts.
    name: Users
  - description: |
      Invite and manage invitations to organisations.
    name: Invitations
  - description: >
      IAM grants are the asignment of roles or permissions to principals to
      manage resource access.
    name: IAM Grants
  - description: |
      View the permissions available in the system.
    name: IAM Permissions
  - description: |
      SSO providers are the identity providers for an organisation.
    name: SSO Providers
  - description: |
      Whoami returns information about the currently authenticated principal.
    name: Whoami
  - description: |
      Manage your images
    name: Images
  - description: >
      AI agent personas that synthesise data into role-specific intelligent
      briefings.
    name: Agents
  - description: |
      Briefings generated by AI agents, including reasoning traces.
    name: Briefings
  - description: >
      Organisations are the center point for most resources in the platform.
      Most other endpoints are subresources of an organisation.
    name: Organisations
  - description: |
      Permits managements, integrated with street manager.
    name: Permits
  - description: |
      Projects manage your work and governance.
    name: Projects
  - description: >
      Import templates allow users to save and reuse their CSV importer
      configuration as named templates.
    name: Import Templates
  - description: |
      Properties are the physical locations.
    name: Properties
  - description: |
      Search across schemes, work orders, and operations.
    name: Search
  - description: |
      Provides the API specification in JSON and YAML formats
    name: Specifications
  - description: |
      Streets are the physical roads.
    name: Streets
  - description: |
      Integration with street manager
    name: Street Manager
  - description: |
      Vehicles are the physical vehicles that an organisation manages.
    name: Vehicles
  - description: >
      Scheme contracts (also known as regions) group schemes allocated from the
      network to a contractor.
    name: Scheme Contracts
  - description: >
      Scheme shares allow you to share your schemes with other organisations
      across bridges.
    name: Scheme Shares
  - description: |
      Schemes are large programmes of work
    name: Schemes
  - description: |
      Work orders the component parts of a scheme.
    name: Work Orders
  - description: |
      Operations are the work to be carried out within work orders.
    name: Operations
externalDocs:
  description: More documentation and resources
  url: https://docs.ctrl-hub.com
paths:
  /v3/reports:
    post:
      tags:
        - Reports
      summary: Create a new report
      description: >
        Schedule a saved query's results for delivery.


        The report runs as the caller: every run executes with the creator's
        real materialised

        grants, so a report can never surface rows its owner could not see for
        themselves. The

        query must exist and the caller must be able to view it.
      operationId: CreateReport
      requestBody:
        $ref: '#/components/requestBodies/CreateReport'
      responses:
        '201':
          $ref: '#/components/responses/GetReport'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - Session: []
        - Cookie: []
        - OAuth2: []
components:
  requestBodies:
    CreateReport:
      required: true
      description: The report to create.
      content:
        application/vnd.api+json:
          schema:
            type: object
            required:
              - data
            properties:
              data:
                type: object
                required:
                  - type
                  - attributes
                  - relationships
                properties:
                  type:
                    type: string
                    const: reports
                  attributes:
                    type: object
                    required:
                      - name
                      - format
                      - schedule
                      - recipients
                    properties:
                      name:
                        type: string
                        description: >-
                          What the report is called, and the subject line
                          recipients see.
                      format:
                        $ref: '#/components/schemas/ReportFormat'
                      schedule:
                        $ref: '#/components/schemas/ReportSchedule'
                      recipients:
                        type: array
                        minItems: 1
                        description: >-
                          Who the report is delivered to. At least one is
                          required.
                        items:
                          $ref: '#/components/schemas/ReportRecipient'
                      options:
                        $ref: '#/components/schemas/ReportOptions'
                  relationships:
                    type: object
                    required:
                      - organisation
                      - query
                    description: >
                      The owner is not settable. A report runs as whoever
                      created it, so the owner

                      is taken from the authenticated caller rather than the
                      request body.
                    properties:
                      organisation:
                        type: object
                        required:
                          - data
                        properties:
                          data:
                            $ref: '#/components/schemas/OrganisationRelationship'
                      query:
                        type: object
                        required:
                          - data
                        properties:
                          data:
                            $ref: '#/components/schemas/QueryRelationship'
  responses:
    GetReport:
      description: An individual report.
      headers:
        Content-Type:
          $ref: '#/components/headers/content-type'
        Content-Length:
          $ref: '#/components/headers/content-length'
        X-Request-ID:
          $ref: '#/components/headers/x-request-id'
      content:
        application/vnd.api+json:
          schema:
            allOf:
              - type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Report'
                  included:
                    $ref: '#/components/schemas/ReportIncludes'
              - $ref: '#/components/schemas/JSONAPI'
    BadRequest:
      description: >
        There was an error with the request - this could be due to an invalid
        body, query parameters,

        or headers that were sent to the API.
      headers:
        Content-Type:
          $ref: '#/components/headers/content-type'
        Content-Length:
          $ref: '#/components/headers/content-length'
        X-Request-ID:
          $ref: '#/components/headers/x-request-id'
      content:
        application/vnd.api+json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/Error'
          example:
            id: 98ca4a78-b66f-4234-9719-aaf832ee6669
            status: '400'
            title: A validation error was encountered
            source:
              parameter: include
            meta:
              resource: wrong_value
    Unauthorised:
      description: Authentication failed
      headers:
        Content-Type:
          $ref: '#/components/headers/content-type'
        Content-Length:
          $ref: '#/components/headers/content-length'
        X-Request-ID:
          $ref: '#/components/headers/x-request-id'
      content:
        application/vnd.api+json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/Error'
          example:
            id: 05fc9c8d-73b9-4697-9337-57f7a567a48f
            status: '401'
            title: You are not authorised to access this resource
            detail: In order to access this resource, you need the 'admin' role.
            code: AUTH.001
    InternalServerError:
      description: There was a problem handling the request on the server side
      headers:
        Content-Type:
          $ref: '#/components/headers/content-type'
        Content-Length:
          $ref: '#/components/headers/content-length'
        X-Request-ID:
          $ref: '#/components/headers/x-request-id'
      content:
        application/vnd.api+json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/Error'
          example:
            id: fe9d9a69-f0a7-4fdc-bb2c-176027f316c5
            status: '500'
            title: Internal Server Error
            detail: An unexpected error occurred on the server.
  schemas:
    ReportFormat:
      type: string
      description: >
        What the recipients receive.


        `csv` attaches the whole result set as a spreadsheet. `digest` is a
        summary email: the

        headline row count, the first rows as a table, and a link into the
        console for the rest.
      enum:
        - csv
        - digest
    ReportSchedule:
      type: object
      description: >
        When a report runs.


        `time` is interpreted in UK time (Europe/London), the same fixed zone
        the analytics

        domain buckets dates and resolves relative-date filters in, so a
        report's schedule and

        the figures in it agree. It is resolved per run rather than stored as an
        offset, so a

        daylight-saving change is absorbed and 09:00 stays 09:00.


        Which anchor applies depends on the frequency, and the anchor a
        frequency does not use is

        ignored:


        - `daily` uses `time` alone.

        - `weekly` uses `day_of_week`.

        - `fortnightly` uses `day_of_week` and `anchor_date`, which decides
        which of the two
          weeks is the running one.
        - `monthly` uses `day_of_month`.

        - `quarterly` uses `day_of_month` of the first month of each quarter
        (January, April,
          July, October).
      required:
        - frequency
        - time
      properties:
        frequency:
          type: string
          description: How often the report runs.
          enum:
            - daily
            - weekly
            - fortnightly
            - monthly
            - quarterly
        time:
          type: string
          pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$
          description: The time of day the report runs, as 24-hour HH:MM in UK time.
          example: '09:00'
        day_of_week:
          type: integer
          minimum: 1
          maximum: 7
          description: >-
            The day of the week for a weekly or fortnightly report, ISO-numbered
            so 1 is Monday and 7 is Sunday.
        day_of_month:
          type: integer
          minimum: 1
          maximum: 31
          description: >
            The day of the month for a monthly or quarterly report.


            A day later than the month contains is clamped to the last day of
            that month, so 31

            means month end in every month rather than being invalid in most of
            them.
        anchor_date:
          type: string
          format: date
          description: >
            Which fortnight a fortnightly report runs in. The report runs in the
            week containing

            this date and every second week after it. Required for `fortnightly`
            and ignored

            otherwise.
    ReportRecipient:
      type: object
      description: >
        Somebody a report is delivered to, named either individually or by the
        team they are in.


        A team is expanded to its current members at send time rather than when
        the report is

        scheduled, so adding somebody to a team starts sending them the report
        and removing them

        stops it.
      required:
        - type
        - id
      properties:
        type:
          type: string
          description: Whether the recipient is one person or a team of them.
          enum:
            - user
            - team
        id:
          type: string
          format: uuid
          description: The id of the user or team.
    ReportOptions:
      type: object
      description: Delivery behaviour that is not the schedule or the format.
      properties:
        skip_empty:
          type: boolean
          default: false
          description: >
            Send nothing when the run returns no rows, recording the run as
            `skipped_empty`

            instead.


            This is what turns a report into an alert: "email me this week's
            critical-risk

            records, but only if there are any".
    OrganisationRelationship:
      type: object
      description: Represents a relationship to an organisation
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the organisation
        type:
          type: string
          const: organisations
    QueryRelationship:
      type: object
      description: Represents a relationship to a query
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the query
        type:
          type: string
          const: queries
    Report:
      type: object
      description: A scheduled delivery of a saved query's results
      required:
        - id
        - type
        - attributes
        - meta
        - relationships
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the report.
        type:
          type: string
          const: reports
        attributes:
          $ref: '#/components/schemas/ReportAttributes'
        meta:
          $ref: '#/components/schemas/ReportMeta'
        relationships:
          $ref: '#/components/schemas/ReportRelationships'
    ReportIncludes:
      type: array
      description: Related resources that can be included when a report is returned.
      items:
        discriminator:
          propertyName: type
          mapping:
            organisations:
              $ref: '#/components/schemas/Organisation'
            queries:
              $ref: '#/components/schemas/Query'
            users:
              $ref: '#/components/schemas/User'
        oneOf:
          - $ref: '#/components/schemas/Organisation'
          - $ref: '#/components/schemas/Query'
          - $ref: '#/components/schemas/User'
    JSONAPI:
      type: object
      description: JSON API response object
      required:
        - jsonapi
      properties:
        jsonapi:
          type: object
          required:
            - version
          properties:
            version:
              type: string
              description: The version of the JSON API specification
              examples:
                - '1.0'
    Error:
      type: object
      description: An error response
      properties:
        id:
          description: >-
            A unique identifier for this particular occurrence of the problem.
            If you encounter this, please provide us with the error ID and we
            can investigate it on our side.
          type: string
          format: uuid
          examples:
            - 05fc9c8d-73b9-4697-9337-57f7a567a48f
        status:
          description: >-
            The status code for the error. This might not match the HTTP status
            code if there are more that one errors to return with different
            status codes.
          type: string
          examples:
            - '401'
            - '500'
        title:
          description: A human readable title for the error.
          type: string
          examples:
            - You are not authorised to access this resource
        detail:
          description: >-
            Where there is more detail that we can provide outside of the title,
            we will provide it here.
          type: string
          examples:
            - In order to access this resource, you need the 'admin' role.
        code:
          description: >-
            A unique code for the error that may help us to diagnose the issue.
            Not all errors have codes, so this is usually empty.
          type: string
          examples:
            - AUTH.001
        source:
          description: A JSON object containing additional information about the error.
          type: object
          properties:
            pointer:
              description: >-
                A JSON Pointer to the value in the request that caused the
                error.
              type: string
              examples:
                - /data/attributes/email
            parameter:
              description: >-
                A string indicating which query parameter in the request caused
                the error.
              type: string
              examples:
                - include
      required:
        - id
        - status
        - title
    ReportAttributes:
      type: object
      description: Attributes of a report
      required:
        - name
        - format
        - schedule
        - recipients
        - state
      properties:
        name:
          type: string
          description: What the report is called, and the subject line recipients see.
        format:
          $ref: '#/components/schemas/ReportFormat'
        schedule:
          $ref: '#/components/schemas/ReportSchedule'
        recipients:
          type: array
          minItems: 1
          description: >-
            Who the report is delivered to. A report with no recipients cannot
            be saved.
          items:
            $ref: '#/components/schemas/ReportRecipient'
        options:
          $ref: '#/components/schemas/ReportOptions'
        state:
          $ref: '#/components/schemas/ReportState'
        paused_reason:
          type:
            - string
            - 'null'
          description: >
            Why the report was paused, when it was paused by the system rather
            than by somebody.

            Null on an active report and on one a person paused.
    ReportMeta:
      type: object
      description: Metadata for a report
      required:
        - created_at
        - updated_at
      properties:
        created_at:
          type: string
          format: date-time
          description: The date and time the report was created.
        updated_at:
          type: string
          format: date-time
          description: The date and time the report was last updated.
        next_run_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            When the report is next due to run. Null on a paused report, which
            has no next run

            until it is resumed.
        last_run_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the report last ran, whatever the outcome. Null before its
            first run.
    ReportRelationships:
      type: object
      description: Relationships for a report
      required:
        - organisation
        - query
        - owner
      properties:
        organisation:
          type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/OrganisationRelationship'
        query:
          type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/QueryRelationship'
          description: The saved query the report runs.
        owner:
          type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/UserRelationship'
          description: >
            Whose access the report runs under. Set to whoever created the
            report and not

            caller-supplied: every run executes with this user's real
            materialised grants, so a

            report can never surface rows its owner could not see for
            themselves.
    Organisation:
      type: object
      description: An organisation
      required:
        - id
        - type
        - attributes
        - meta
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the organisation.
        type:
          type: string
          const: organisations
        attributes:
          $ref: '#/components/schemas/OrganisationAttributes'
        meta:
          $ref: '#/components/schemas/OrganisationMeta'
        relationships:
          $ref: '#/components/schemas/OrganisationRelationships'
    Query:
      type: object
      description: A saved query definition
      required:
        - id
        - type
        - attributes
        - meta
        - relationships
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the query.
        type:
          type: string
          const: queries
        attributes:
          $ref: '#/components/schemas/QueryAttributes'
        meta:
          $ref: '#/components/schemas/QueryMeta'
        relationships:
          $ref: '#/components/schemas/QueryRelationships'
    User:
      type: object
      description: A user
      required:
        - id
        - type
        - attributes
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the user.
          examples:
            - 123e4567-e89b-12d3-a456-426614174000
        type:
          type: string
          const: users
        attributes:
          $ref: '#/components/schemas/UserAttributes'
        meta:
          $ref: '#/components/schemas/UserMeta'
        relationships:
          $ref: '#/components/schemas/UserRelationships'
    ReportState:
      type: string
      description: >
        Whether the report is running to its schedule.


        A report is paused either because somebody paused it or because it
        stopped being able to

        run as its owner: the owner's account was disabled, their access was
        revoked, or the

        organisation was made inactive. The owner is notified when that happens,
        so a report never

        goes quiet without saying so.
      enum:
        - active
        - paused
    UserRelationship:
      type: object
      description: Represents a relationship to a user
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the user
        type:
          type: string
          const: users
    OrganisationAttributes:
      type: object
      description: Attributes for an organisation
      required:
        - name
        - slug
        - sandbox
      properties:
        name:
          type: string
          description: The name of the organisation.
          examples:
            - Acme Construction Ltd
        slug:
          type: string
          description: The URL-friendly identifier for the organisation.
          examples:
            - acme-construction
        description:
          type: string
          description: A short description of the organisation.
          examples:
            - >-
              Leading construction company specializing in infrastructure
              projects
        sandbox:
          type: boolean
          description: Whether the organisation is a sandbox (i.e. a test organisation)
          examples:
            - false
        settings:
          type: object
          properties:
            teams:
              type: object
              description: Team-related settings for the organisation.
              properties:
                customer_representatives:
                  type: array
                  description: >
                    IDs of teams within this organisation whose members act as

                    customer service representatives. Each entry must reference
                    a

                    team that belongs to this organisation.
                  items:
                    type: string
                    format: uuid
                  uniqueItems: true
                  examples:
                    - - b234c567-8901-2345-6789-abcdef012345
    OrganisationMeta:
      type: object
      description: Meta information for an organisation
      required:
        - v3
        - status
      properties:
        created_at:
          type: string
          format: date-time
          description: The creation time of the organisation.
          examples:
            - '2023-01-15T10:30:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: The last update time of the organisation.
          examples:
            - '2023-02-20T14:45:00.000Z'
        v3:
          type: boolean
          description: Whether the organisation is using version 3 exclusively.
          examples:
            - true
        status:
          type: string
          enum:
            - active
            - inactive
          default: active
          description: The current status of the organisation.
          examples:
            - active
        features:
          type: array
          description: Available features and their limits for the organisation.
          items:
            type: object
            properties:
              name:
                type: string
                description: The name of the feature.
                examples:
                  - advanced_reporting
              enabled:
                type: boolean
                description: Whether the feature is enabled.
                examples:
                  - true
              limit:
                type: integer
                description: The usage limit for this feature (if applicable).
                examples:
                  - 1000
    OrganisationRelationships:
      type: object
      description: Relationships for an organisation
      properties:
        users:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/UserRelationship'
        service_accounts:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/ServiceAccountRelationship'
        groups:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/UserGroupRelationship'
        teams:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/TeamRelationship'
        nomenclature:
          type: object
          required:
            - data
          properties:
            data:
              oneOf:
                - $ref: '#/components/schemas/NomenclatureRelationship'
                - type: 'null'
    QueryAttributes:
      type: object
      description: Attributes of a query definition
      required:
        - name
        - dataset
        - mode
      properties:
        name:
          type: string
          description: The display name of the query.
        description:
          type: string
          description: A description of the query.
        dataset:
          type: string
          enum:
            - form-submissions
          description: The dataset the query runs against. v1 supports "form-submissions".
        mode:
          type: string
          enum:
            - detail
            - aggregate
          description: >-
            detail returns one row per submission; aggregate groups by
            dimensions and computes measures.
        fields:
          type: array
          description: >-
            Selected columns (detail mode). Key is a stable schema field id or a
            spine column.
          items:
            type: object
            required:
              - key
            properties:
              key:
                type: string
              label:
                type: string
              type:
                type: string
              decimals:
                type: integer
                minimum: 0
                maximum: 10
                description: >-
                  How many decimal places the column is shown to, in the results
                  grid and the CSV export alike. Omitted means the value is
                  shown as stored: a detail column reports what a submission
                  recorded, so it is only shortened when asked. Applies to
                  numeric columns; ignored on any other.
              resolution:
                type: object
                description: >-
                  Live relationship-traversal projections for an x-source
                  column. Each projection follows a relationship path from the
                  column's resource and displays a chosen attribute of the
                  terminal resource, resolved live at read time (authorised per
                  hop). Only meaningful for an x-source column.
                properties:
                  projections:
                    type: array
                    items:
                      type: object
                      required:
                        - path
                      properties:
                        path:
                          type: array
                          description: >-
                            Ordered relationship names to follow from the
                            column's resource. An empty path projects the
                            column's own resource.
                          items:
                            type: string
                        attribute:
                          type: string
                          description: >-
                            The JSON:API attribute of the terminal resource to
                            display. Empty uses the resource's default label.
                        label:
                          type: string
                          description: Overrides the default column heading.
                        multi_value:
                          type: string
                          enum:
                            - join
                            - first
                            - count
                            - distinct-columns
                          description: >-
                            How a to-many terminal set renders across output
                            columns.
        group_by:
          type: array
          description: >-
            Dimension fields (aggregate mode). Key is a stable schema field id
            or a spine column; label is the human-readable column heading.
          items:
            type: object
            required:
              - key
            properties:
              key:
                type: string
              label:
                type: string
              type:
                type: string
                description: >-
                  The dimension's declared value type (string, number, boolean,
                  date, datetime, choice, ...). Required for a date field that
                  carries a bucket, since only the form knows a payload field's
                  type.
              bucket:
                type: string
                enum:
                  - day
                  - week
                  - month
                  - quarter
                  - year
                description: >-
                  Time grain to group a date dimension at, so a date groups per
                  week or month rather than per instant. Only valid on a date
                  dimension: a date-typed field, or the created_at column, whose
                  type the server knows and so does not require. The group value
                  is the first day of the bucket as an ISO date. That constraint
                  is enforced by the service on create, update and preview (a
                  400 naming the dimension) rather than by this schema, since it
                  depends on the referenced field's declared type.
              bin:
                type: object
                description: >-
                  Bands to group a numeric dimension into, so a continuous value
                  groups into a handful of ranges rather than one group per
                  distinct value. Describe the bands EITHER by a width (with
                  from, and optionally to) OR by explicit thresholds, never
                  both. Only valid on a numeric dimension: a number, integer or
                  duration field, or the iteration column, whose type the server
                  knows and so does not require. A dimension may not carry both
                  a bin and a bucket. All the constraints here, including the
                  band-count cap, are enforced by the service on create, update
                  and preview (a 400 naming the dimension) rather than by this
                  schema, since they depend on the referenced field's declared
                  type. The group value is the band's own lower bound in the
                  field's stored unit, or "-inf" for the band below the first,
                  so a client can label the band and drill through it.
                properties:
                  from:
                    type: number
                    description: >-
                      Lower bound of the first band, and the anchor every other
                      band is measured from. Values below it group into a band
                      of their own rather than being folded into the first.
                      Anchoring here rather than at the smallest value in the
                      data is what keeps a band stable as the data changes.
                  width:
                    type: number
                    description: >-
                      How wide each band is, in the field's stored unit, which
                      for a duration is seconds (3600 is an hour). A non-zero
                      width describes the bands by width; leave it out to
                      describe them by thresholds instead.
                  to:
                    type: number
                    description: >-
                      Optional upper bound of the width bands. Everything at or
                      above it groups into a single open-ended top band, which
                      is what makes a "2h+" band possible. Setting it also makes
                      the band count arithmetic, so an excessive one is refused
                      rather than silently widened; an open-ended bin's band
                      count is whatever the data spans.
                  thresholds:
                    type: array
                    minItems: 1
                    items:
                      type: number
                    description: >-
                      Explicit ascending lower bounds of each band, in the
                      field's stored unit, for named bands such as 0-1h / 1-2h /
                      2h+. The last band is open-ended. Values below the first
                      threshold group into a band of their own. A non-empty list
                      describes the bands by threshold; leave it out to describe
                      them by width instead.
        measures:
          type: array
          description: Aggregated values (aggregate mode).
          items:
            type: object
            required:
              - func
            properties:
              key:
                type: string
                description: >-
                  The field aggregated over. Optional for count, which counts
                  submissions rather than a field's values.
              func:
                type: string
                enum:
                  - count
                  - count_distinct
                  - sum
                  - avg
                  - min
                  - max
                  - median
                  - percentile
              type:
                type: string
                description: >-
                  The declared value type of the field being aggregated (number,
                  integer, duration, string, choice, ...). Needed by the
                  functions that only mean something over a number (sum, avg,
                  min, max, median, percentile) on a payload field, since only
                  the form knows a field type. Omitting it is not refused, so a
                  measure saved before this existed still runs; declaring a
                  non-numeric type for one of those functions is a 400 naming
                  the field, enforced by the service on create, update and
                  preview rather than by this schema.
              percentile:
                type: integer
                minimum: 1
                maximum: 99
                description: >-
                  Which percentile to compute, as a whole number of percent, for
                  the percentile function only. Required by it and ignored by
                  every other function. Whole numbers 1-99: the 0th and 100th
                  are the minimum and the maximum, which have functions of their
                  own, and a fractional percentile is not admitted because the
                  output column is keyed p<n>_<fieldid> and a dot in that key
                  reads client-side as the separator marking a
                  resolved-projection column. Use median where that is the word
                  you mean.
              decimals:
                type: integer
                minimum: 0
                maximum: 10
                description: >-
                  How many decimal places the figure is shown to, in the results
                  grid and the CSV export alike. Omitted means 2 for every
                  function that computes a value, because an aggregate
                  manufactures precision the data never had (an average of 1, 1
                  and 5 is 2.3333333333333335, and an interpolated percentile of
                  whole numbers is 7.399999999999999). count and count_distinct
                  are whole numbers and are never rounded.
              label:
                type: string
        filters:
          type: array
          description: Constraints applied to the rows the query executes over.
          items:
            type: object
            required:
              - key
              - op
            properties:
              key:
                type: string
              op:
                type: string
              values:
                type: array
                items:
                  type: string
        sort:
          type: array
          description: Ordering applied to query results.
          items:
            type: object
            required:
              - key
            properties:
              key:
                type: string
              direction:
                type: string
                enum:
                  - asc
                  - desc
        column_order:
          type: array
          description: >-
            Full display order of detail-mode result columns by key, including
            resolved projection columns (e.g. "<fieldKey>.scheme.name"). Empty
            falls back to fields order with projections grouped after their
            parent.
          items:
            type: string
    QueryMeta:
      type: object
      description: Metadata for a query
      required:
        - created_at
        - updated_at
      properties:
        created_at:
          type: string
          format: date-time
          description: The date and time the query was created.
        updated_at:
          type: string
          format: date-time
          description: The date and time the query was last updated.
    QueryRelationships:
      type: object
      description: Relationships for a query
      required:
        - organisation
      properties:
        organisation:
          type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/OrganisationRelationship'
        form:
          type: object
          properties:
            data:
              oneOf:
                - type: object
                  required:
                    - type
                    - id
                  properties:
                    type:
                      type: string
                      const: forms
                    id:
                      type: string
                      format: uuid
                - type: 'null'
              description: >-
                The form this query targets (for the form-submissions dataset).
                Null for dataset-level queries.
    UserAttributes:
      type: object
      description: Attributes for a user
      properties:
        email:
          type: string
          format: email
          description: The email address of the user.
          examples:
            - john.doe@example.com
        status:
          type: string
          enum:
            - active
            - inactive
            - pending
            - unknown
          description: >
            The membership status of this user in the organisation in the
            request URL.

            Only populated on org-scoped member endpoints; absent on global user

            endpoints.
          examples:
            - active
        identities:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
                description: The unique identifier for the identity.
                examples:
                  - 39ce13b8-1116-416a-ad5f-3c5edfd44f53
              platform:
                type: string
                description: The platform of the identity.
                examples:
                  - multi_tenant
              meta:
                type:
                  - object
                  - 'null'
                additionalProperties: true
                description: Additional metadata for the identity.
        profile:
          type: object
          properties:
            work:
              type: object
              properties:
                occupation:
                  type: string
                  description: The occupation of the user.
                  examples:
                    - Site Manager
                cscs:
                  type: string
                  description: The CSCS card number of the user.
                  examples:
                    - CSC123456
                eusr:
                  type: string
                  description: The EUSR card number of the user.
                  examples:
                    - EUR789123
                start_date:
                  type: string
                  format: date
                  description: The start date of the user's employment.
                  examples:
                    - '2020-03-01T00:00:00.000Z'
            personal:
              type: object
              properties:
                first_name:
                  type: string
                  description: The first name of the user.
                  examples:
                    - John
                last_name:
                  type: string
                  description: The last name of the user.
                  examples:
                    - Doe
                dob:
                  type: string
                  format: date
                  description: The date of birth of the user.
                  examples:
                    - '1985-06-15T00:00:00.000Z'
                username:
                  type: string
                  description: The username of the user.
                  examples:
                    - johndoe
            contact:
              type: object
              properties:
                mobile:
                  type: string
                  description: The mobile number of the user.
                  examples:
                    - +44 7700 900123
                landline:
                  type: string
                  description: The landline of the user.
                  examples:
                    - +44 20 7946 0958
            address:
              type: object
              properties:
                number:
                  type: string
                  description: The house number of the user's address.
                  default: ''
                  examples:
                    - '42'
                street:
                  type: string
                  description: The street of the user's address.
                  examples:
                    - High Street
                area:
                  type: string
                  description: The area of the user's address.
                  examples:
                    - Westminster
                town:
                  type: string
                  description: The town of the user's address.
                  examples:
                    - London
                county:
                  type: string
                  description: The county of the user's address.
                  examples:
                    - Greater London
                postcode:
                  type: string
                  description: The postcode of the user's address.
                  examples:
                    - SW1A 1AA
                country_code:
                  type: string
                  description: The country code of the user's address.
                  examples:
                    - GB
                what3words:
                  type: string
                  description: The what3words location of the user's address.
                  examples:
                    - filled.count.soap
            settings:
              type: object
              properties:
                preferred_language:
                  type: string
                  description: The preferred language of the user.
                  default: en-GB
                  examples:
                    - en-GB
                timezone:
                  type: string
                  description: The timezone of the user.
                  examples:
                    - Europe/London
    UserMeta:
      type: object
      description: Metadata for a user
      properties:
        managed_type:
          type: string
          enum:
            - none
            - scim
            - organisation
            - unknown
          description: How this user is managed.
    UserRelationships:
      type: object
      description: Relationships for a user
      properties:
        organisations:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/OrganisationRelationship'
        teams:
          type: object
          required:
            - data
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/TeamRelationship'
        managing_organisation:
          type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/OrganisationRelationship'
    ServiceAccountRelationship:
      type: object
      description: Represents a relationship to a service account
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the service account
        type:
          type: string
          const: service-accounts
    UserGroupRelationship:
      type: object
      description: Represents a relationship to a group
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the group
        type:
          type: string
          const: groups
    TeamRelationship:
      type: object
      description: Represents a relationship to a team
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the team
        type:
          type: string
          const: teams
    NomenclatureRelationship:
      type: object
      description: Represents a relationship to a nomenclature resource
      required:
        - id
        - type
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the nomenclature resource
        type:
          type: string
          const: nomenclature
  headers:
    content-type:
      description: The content type of the response
      schema:
        type: string
      example: application/vnd.api+json
    content-length:
      description: The length of the response body in bytes
      schema:
        type: integer
        format: int32
      example: 1234
    x-request-id:
      description: >-
        An ID that can be provided when reporting bugs to help identify the
        issue
      schema:
        type: string
      example: 8470f56af4cf25e22be08e72c70dbbdc
  securitySchemes:
    Session:
      description: |
        Session token for authentication.
      in: header
      name: X-Session-Token
      type: apiKey
    Cookie:
      description: |
        Cookie token for authentication.
      in: cookie
      name: ctrl_hub_session
      type: apiKey
    OAuth2:
      description: |
        OAuth2 token for authentication.
      flows:
        clientCredentials:
          scopes: {}
          tokenUrl: https://auth.ctrl-hub.com/oauth2/token
      type: oauth2

````