Coperniq projects API

The projects API from Coperniq — 3 operation(s) for projects.

OpenAPI Specification

coperniq-projects-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: API Key accounts projects API
  version: 1.0.0
servers:
- url: https://api.coperniq.io/v1
  description: Production server
tags:
- name: projects
paths:
  /projects:
    get:
      operationId: list-projects
      summary: List Projects
      description: 'Retrieve a paginated list of projects.


        Supports:

        - Pagination (`page_size`, `page`)

        - Date filtering (`updated_after`, `updated_before`)

        - Sorting (`order_by`)

        - Field search (`title`, `address`, `primaryName`, `primaryPhone`, `primaryEmail`)

        - Full text search (`q`)


        **Note:** If a project has no `title` (empty or whitespace-only), the response returns the parent account''s `title` instead. The stored value is not modified — this is a read-time fallback only. Title-based search (`title` query param, full-text `q`, or the `/projects/search` endpoint with `prop=title&op=contains`) also matches projects whose own title is null/empty when the parent account''s title matches the search term.

        '
      tags:
      - projects
      parameters:
      - name: page_size
        in: query
        description: Number of items per page (max 100)
        required: false
        schema:
          type: integer
          default: 20
      - name: page
        in: query
        description: Page number (1-based)
        required: false
        schema:
          type: integer
          default: 1
      - name: updated_after
        in: query
        description: Filter items updated after this timestamp (ISO 8601)
        required: false
        schema:
          type: string
          format: date-time
      - name: updated_before
        in: query
        description: Filter items updated before this timestamp (ISO 8601)
        required: false
        schema:
          type: string
          format: date-time
      - name: order_by
        in: query
        description: Sort order for results
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsGetParametersOrderBy'
      - name: include_virtual_properties
        in: query
        description: Whether to include virtual properties in the response. Defaults to false unless explicitly set to true.
        required: false
        schema:
          type: boolean
          default: false
      - name: include_archived
        in: query
        description: Whether to include archived (inactive) records in the response. By default only active records are returned.
        required: false
        schema:
          type: boolean
          default: false
      - name: q
        in: query
        description: Full text search query
        required: false
        schema:
          type: string
      - name: title
        in: query
        description: Title search query
        required: false
        schema:
          type: string
      - name: address
        in: query
        description: Address search query
        required: false
        schema:
          type: string
      - name: primaryName
        in: query
        description: Contact name search query
        required: false
        schema:
          type: string
      - name: primaryPhone
        in: query
        description: Contact phone search query
        required: false
        schema:
          type: string
      - name: primaryEmail
        in: query
        description: Contact email search query
        required: false
        schema:
          type: string
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: List of projects
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Project'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListProjectsRequestUnauthorizedError'
    post:
      operationId: create-project
      summary: Create Project
      description: 'Create a new project with required and optional fields.


        Required fields:

        - `title`: Project title/name

        - `address`: An array containing a single string, which represents the full project location/address.


        Optional fields:

        - `trades`: Array of trade types

        - `accountId`: Link to existing account

        - `workflowId`: Link to workflow

        - `phaseId`: Link to phase

        - `primaryEmail`/`primaryPhone`: Contact information

        - `contacts`: Contact IDs only (no name, email, phone, etc.). The contacts must be created first via POST /contacts.

        - `custom`: Custom fields object


        Note: If primaryEmail or primaryPhone is provided, a contact will be automatically created or matched.

        '
      tags:
      - projects
      parameters:
      - name: allow_new_options
        in: query
        description: Whether to allow creation of new dropdown options during record creation
        required: false
        schema:
          type: boolean
          default: false
      - name: match_by
        in: query
        description: Field to use for matching existing records
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsPostParametersMatchBy'
      - name: match_found_strategy
        in: query
        description: Strategy to use when a match is found
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsPostParametersMatchFoundStrategy'
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Matching project found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProjectRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProjectRequestUnauthorizedError'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProjectCreate'
  /projects/search:
    get:
      operationId: search-projects
      summary: Search Projects
      description: "Search projects using up to two filters (prop1/op1/value1 and optionally prop2/op2/value2), combined with `logic` (AND/OR).\n\nProperties:\n- `propX` can be a standard field (e.g., `status`, `title`, `city`, `type`, `accountId`, etc.) or a custom property key name.\n- Use the `property key` from your company settings.\n- Filter by parent account with `accountId`. `clientId` is accepted as a deprecated alias for backwards compatibility.\n\nOperators (`opX`):\n- Equality: `eq`, `neq`\n- Numeric/datetime comparisons: `gt`, `gte`, `lt`, `lte`\n- Text/string matching: `contains` (case-insensitive)\n- Lists: `in`, `nin` (CSV list in `valueX`)\n- Ranges: `between` (use `valueX` as `from,to`)\n- Existence: `exists` is not supported for custom properties due to performance limitations. Use `eq` or `neq` instead.\n\nValue formats:\n- `in`/`nin`: lists can be provided as:\n  - Plain CSV: `value1=OPEN,ACTIVE`\n  - Quoted CSV (to include commas inside a value): `value1=\"Last, First\",Other`\n  - JSON array: `value1=[\"Last, First\",\"Other\"]`\n- `between`: `from,to` (e.g., `value1=2025-01-01,2025-12-31` or `value1=10,20`)\n- Dates should be ISO 8601 strings; numeric-like values on custom properties are matched against both numeric and text representations.\n\nExamples:\n- status equals ACTIVE: `?prop1=status&op1=eq&value1=ACTIVE`\n- custom id equals 1234: `?prop1=legacy_tool_project_id&op1=eq&value1=1234`\n- title contains \"Solar\": `?prop1=name&op1=contains&value1=Solar`\n- status IN (ACTIVE, ON_HOLD) AND city = Austin: `?prop1=status&op1=in&value1=ACTIVE,ON_HOLD&logic=and&prop2=city&op2=eq&value2=Austin`\n\n**Note:** If a project has no `title` (empty or whitespace-only), the response returns the parent account's `title` instead. The stored value is not modified — this is a read-time fallback only. Title-based search (`title` query param, full-text `q`, or the `/projects/search` endpoint with `prop=title&op=contains`) also matches projects whose own title is null/empty when the parent account's title matches the search term.\n"
      tags:
      - projects
      parameters:
      - name: prop1
        in: query
        description: First field to filter (standard or custom keyName)
        required: true
        schema:
          type: string
      - name: op1
        in: query
        description: Operator for prop1
        required: true
        schema:
          $ref: '#/components/schemas/ProjectsSearchGetParametersOp1'
      - name: value1
        in: query
        description: Value for prop1 (comma-separated values for in/nin or between)
        required: true
        schema:
          type: string
      - name: logic
        in: query
        description: Logical combination when both prop1 and prop2 are provided
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsSearchGetParametersLogic'
      - name: prop2
        in: query
        description: Optional second field to filter
        required: false
        schema:
          type: string
      - name: op2
        in: query
        description: Operator for prop2
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsSearchGetParametersOp2'
      - name: value2
        in: query
        description: Value for prop2 (comma-separated values for in/nin or between)
        required: false
        schema:
          type: string
      - name: page_size
        in: query
        description: Number of items per page (max 100)
        required: false
        schema:
          type: integer
          default: 20
      - name: page
        in: query
        description: Page number (1-based)
        required: false
        schema:
          type: integer
          default: 1
      - name: order_by
        in: query
        description: Sort order for results
        required: false
        schema:
          $ref: '#/components/schemas/ProjectsSearchGetParametersOrderBy'
      - name: include_archived
        in: query
        description: Whether to include archived (inactive) records in the response. By default only active records are returned.
        required: false
        schema:
          type: boolean
          default: false
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: List of projects matching filters
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Project'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchProjectsRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchProjectsRequestUnauthorizedError'
  /projects/{projectId}:
    get:
      operationId: get-project
      summary: Get Project
      description: 'Retrieve a specific project by ID.


        **Note:** If the project has no `title` (empty or whitespace-only), the response returns the parent account''s `title` instead. The stored value is not modified — this is a read-time fallback only.

        '
      tags:
      - projects
      parameters:
      - name: projectId
        in: path
        description: Project identifier
        required: true
        schema:
          type: integer
      - name: include_virtual_properties
        in: query
        description: Whether to include virtual properties in the response. Defaults to false unless explicitly set to true.
        required: false
        schema:
          type: boolean
          default: false
      - name: include_archived
        in: query
        description: Whether to include archived (inactive) records in the response. By default only active records are returned.
        required: false
        schema:
          type: boolean
          default: false
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Project details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectWithPhaseInstances'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetProjectRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetProjectRequestNotFoundError'
    patch:
      operationId: update-project
      summary: Update Project
      description: 'Update an existing project. Supports partial updates.


        Updatable fields:

        - Standard fields (value, size, status, etc.)

        - Workflow fields (workflowId, phaseId)

        - Contact information (primaryEmail, primaryPhone)

        - Contacts (contact IDs only, no name, email, phone, etc.)

        - Custom fields (through custom object)


        Note: Updates are atomic - either all fields update or none do.


        > **Changing account association is not supported via update.** To move a project to a different account, delete and re-create it under the new account.

        '
      tags:
      - projects
      parameters:
      - name: projectId
        in: path
        description: Project identifier
        required: true
        schema:
          type: integer
      - name: allow_new_options
        in: query
        description: Whether to allow creation of new dropdown options during record creation
        required: false
        schema:
          type: boolean
          default: false
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Project updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateProjectRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateProjectRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateProjectRequestNotFoundError'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProjectUpdate'
    delete:
      operationId: delete-project
      summary: Delete Project
      description: Delete a specific project by ID
      tags:
      - projects
      parameters:
      - name: projectId
        in: path
        description: Project identifier
        required: true
        schema:
          type: integer
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Successful response
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteProjectRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteProjectRequestNotFoundError'
components:
  schemas:
    ProjectsSearchGetParametersOp1:
      type: string
      enum:
      - eq
      - neq
      - gt
      - gte
      - lt
      - lte
      - contains
      - in
      - nin
      - between
      title: ProjectsSearchGetParametersOp1
    ProjectsPostResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - UNAUTHORIZED
      title: ProjectsPostResponsesContentApplicationJsonSchemaCode
    CreateProjectRequestBadRequestError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsPostResponsesContentApplicationJsonSchemaCode'
        field:
          type: string
          description: Field that caused the validation error (if applicable)
      title: CreateProjectRequestBadRequestError
    ProjectsGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - UNAUTHORIZED
      title: ProjectsGetResponsesContentApplicationJsonSchemaCode
    ProjectsProjectIdGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: ProjectsProjectIdGetResponsesContentApplicationJsonSchemaCode
    ProjectUpdate:
      type: object
      properties:
        title:
          type: string
          description: Project title/name
        description:
          type:
          - string
          - 'null'
          description: Project description
        address:
          type: array
          items:
            type: string
          description: An array containing a single string, which represents the full project location/address.
        trades:
          type: array
          items:
            type: string
          description: Array of trade types
        workflowId:
          type: string
          description: ID of associated workflow
        value:
          type: number
          format: double
          description: Project value
        size:
          type: number
          format: double
          description: Project size
        status:
          $ref: '#/components/schemas/ProjectStatus'
        primaryEmail:
          type: string
          format: email
          description: Primary contact email
        primaryPhone:
          type: string
          description: Primary contact phone
        contacts:
          type: array
          items:
            type: integer
          description: Contact IDs only (no name, email, phone, etc.). The contacts must be created first via POST /contacts.
        custom:
          type: object
          additionalProperties:
            description: Any type
          description: Custom fields
      description: 'All fields are optional. Changing account association is not supported via update — delete and re-create the project under the new account.

        '
      title: ProjectUpdate
    ProjectStatus:
      type: string
      enum:
      - ACTIVE
      - ON_HOLD
      - CANCELLED
      - COMPLETED
      description: 'Status of the project:

        * `ACTIVE` - Project is active and in progress

        * `ON_HOLD` - Project is temporarily paused

        * `CANCELLED` - Project has been cancelled

        * `COMPLETED` - Project has been completed

        '
      title: ProjectStatus
    SearchProjectsRequestBadRequestError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsSearchGetResponsesContentApplicationJsonSchemaCode'
        field:
          type: string
          description: Field that caused the validation error (if applicable)
      title: SearchProjectsRequestBadRequestError
    SearchProjectsRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsSearchGetResponsesContentApplicationJsonSchemaCode'
      title: SearchProjectsRequestUnauthorizedError
    UpdateProjectRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsProjectIdPatchResponsesContentApplicationJsonSchemaCode'
      title: UpdateProjectRequestNotFoundError
    ProjectWithPhaseInstancesStage:
      type: object
      properties:
        id:
          type: integer
          description: Stage identifier
        name:
          type: string
          description: Stage name
        type:
          type: string
          description: Stage type
        scope:
          type: string
          description: Stage scope
        redSla:
          type: integer
          description: Red SLA threshold in days
        yellowSla:
          type: integer
          description: Yellow SLA threshold in days
        timeInStageDays:
          type: integer
          description: Number of days in current stage
        slaStatus:
          $ref: '#/components/schemas/ProjectWithPhaseInstancesStageSlaStatus'
          description: Current SLA violation status
      description: 'Current stage information (Workflows 1.0).


        This object is present only for records still using the original Stage-based workflow engine.

        When the project is managed by Workflows 2.0 (Phase engine) the `stage` object and

        related fields (`stageId`, `timeInStageDays`, `slaStatus`) are omitted.

        '
      title: ProjectWithPhaseInstancesStage
    ProjectsSearchGetParametersOrderBy:
      type: string
      enum:
      - asc
      - desc
      default: asc
      title: ProjectsSearchGetParametersOrderBy
    ProjectsProjectIdPatchResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: ProjectsProjectIdPatchResponsesContentApplicationJsonSchemaCode
    UpdateProjectRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsProjectIdPatchResponsesContentApplicationJsonSchemaCode'
      title: UpdateProjectRequestUnauthorizedError
    ProjectsGetParametersOrderBy:
      type: string
      enum:
      - asc
      - desc
      default: asc
      title: ProjectsGetParametersOrderBy
    ProjectsSearchGetParametersLogic:
      type: string
      enum:
      - and
      - or
      default: and
      title: ProjectsSearchGetParametersLogic
    Project:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier
        createdAt:
          type: string
          format: date-time
          description: Creation timestamp
        updatedAt:
          type: string
          format: date-time
          description: Last update timestamp
        title:
          type: string
          description: Record title/name
        description:
          type:
          - string
          - 'null'
          description: Record description
        address:
          type: array
          items:
            type: string
          description: Record location/address
        isActive:
          type: boolean
          description: Whether the record is active
        primaryEmail:
          type:
          - string
          - 'null'
          format: email
          description: Primary contact email
        primaryPhone:
          type:
          - string
          - 'null'
          description: Primary contact phone
        number:
          type: integer
          description: Record number (e.g., 1234)
        createdBy:
          oneOf:
          - $ref: '#/components/schemas/UserSummary'
          - type: 'null'
          description: User who created the record. Null when the record was created by a non-user actor (e.g. automation or a contact).
        updatedBy:
          oneOf:
          - $ref: '#/components/schemas/UserSummary'
          - type: 'null'
          description: User who last edited a field on the record, derived from the changelog. Null when the record has never been edited or the last edit was made by a non-user actor.
        custom:
          type: object
          additionalProperties:
            description: Any type
          description: Custom fields
        trades:
          type: array
          items:
            type: string
          description: Array of trade types
        value:
          type:
          - number
          - 'null'
          format: double
          description: Project value
        size:
          type:
          - number
          - 'null'
          format: double
          description: Project size
        workflowId:
          type:
          - integer
          - 'null'
          description: Associated workflow ID
        accountId:
          type:
          - integer
          - 'null'
          description: Associated account ID
        status:
          $ref: '#/components/schemas/ProjectStatus'
        stage:
          $ref: '#/components/schemas/ProjectStage'
          description: 'Current stage information (Workflows 1.0).


            This object is present only for records still using the original Stage-based workflow engine.

            When the project is managed by Workflows 2.0 (Phase engine) the `stage` object and

            related fields (`stageId`, `timeInStageDays`, `slaStatus`) are omitted.

            '
        phase:
          $ref: '#/components/schemas/ProjectPhase'
          description: 'Current phase information (Workflows 2.0).


            This object replaces `stage` when a project is attached to the Phase-based workflow engine.

            If the project is still on Workflows 1.0 this object will be omitted.

            '
        workflowName:
          type: string
          description: 'Name of the associated workflow.

            '
      title: Project
    PhaseTemplateSummary:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        type:
          type: string
        redSla:
          type:
          - integer
          - 'null'
        yellowSla:
          type:
          - integer
          - 'null'
      title: PhaseTemplateSummary
    ProjectStageSlaStatus:
      type: string
      enum:
      - VIOLATED
      - NON_VIOLATED
      description: Current SLA violation status
      title: ProjectStageSlaStatus
    ProjectWithPhaseInstancesPhaseInstancesItems:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        status:
          $ref: '#/components/schemas/ProjectWithPhaseInstancesPhaseInstancesItemsStatus'
        position:
          type: integer
        type:
          type: string
        phaseTemplateId:
          type: integer
        phaseTemplate:
          $ref: '#/components/schemas/PhaseTemplateSummary'
        startedAt:
          type:
          - string
          - 'null'
          format: date-time
          description: Timestamp when the phase instance started (get project by id only)
        completedAt:
          type:
          - string
          - 'null'
          format: date-time
          description: Timestamp when the phase instance completed (get project by id only)
      title: ProjectWithPhaseInstancesPhaseInstancesItems
    DeleteProjectRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsProjectIdDeleteResponsesContentApplicationJsonSchemaCode'
      title: DeleteProjectRequestUnauthorizedError
    ProjectWithPhaseInstancesStageSlaStatus:
      type: string
      enum:
      - VIOLATED
      - NON_VIOLATED
      description: Current SLA violation status
      title: ProjectWithPhaseInstancesStageSlaStatus
    ProjectsPostParametersMatchFoundStrategy:
      type: string
      enum:
      - skip
      - replace
      - enrich
      default: skip
      description: '- skip: Return existing record without changes

        - replace: Replace existing record with new data

        - enrich: Update only empty fields in existing record

        '
      title: ProjectsPostParametersMatchFoundStrategy
    ProjectStage:
      type: object
      properties:
        id:
          type: integer
          description: Stage identifier
        name:
          type: string
          description: Stage name
        type:
          type: string
          description: Stage type
        scope:
          type: string
          description: Stage scope
        redSla:
          type: integer
          description: Red SLA threshold in days
        yellowSla:
          type: integer
          description: Yellow SLA threshold in days
        timeInStageDays:
          type: integer
          description: Number of days in current stage
        slaStatus:
          $ref: '#/components/schemas/ProjectStageSlaStatus'
          description: Current SLA violation status
      description: 'Current stage information (Workflows 1.0).


        This object is present only for records still using the original Stage-based workflow engine.

        When the project is managed by Workflows 2.0 (Phase engine) the `stage` object and

        related fields (`stageId`, `timeInStageDays`, `slaStatus`) are omitted.

        '
      title: ProjectStage
    ProjectWithPhaseInstancesPhaseSlaStatus:
      type: string
      enum:
      - VIOLATED
      - NON_VIOLATED
      description: Current SLA violation status for the phase
      title: ProjectWithPhaseInstancesPhaseSlaStatus
    ProjectsPostParametersMatchBy:
      type: string
      enum:
      - title
      - primaryEmail
      - primaryPhone
      - address
      default: title
      title: ProjectsPostParametersMatchBy
    GetProjectRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsProjectIdGetResponsesContentApplicationJsonSchemaCode'
      title: GetProjectRequestUnauthorizedError
    ListProjectsRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsGetResponsesContentApplicationJsonSchemaCode'
      title: ListProjectsRequestUnauthorizedError
    DeleteProjectRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/ProjectsProjectIdDeleteResponsesContentApplicationJsonSchemaCode'
      title: DeleteProjectRequestNotFoundError
    ProjectCreate:
      type: object
      properties:
        title:
          type: string
          description: Project title/name
        description:
          type:
          - string
          - 'null'
          description: Project description
        address:
          type: array
          items:
            type: string
          description: An array containing a single string, which represents the full project location/address.
        trades:
          type: array
          items:
            type: string
          description: Array of trade types, defaults to 'Solar'
        accountId:
          type: string
          description: ID of associated account
        workflowId:
          type: string
          description: ID of associated workflow
        value:
          type: number
          format: double
          description: Project value
        size:
          type: number
          format: double
          description: Project size
        status:
          $ref: '#/components/schemas/ProjectStatus'
        primaryEmail:
          type: string
          format: email
          description: Primary contact email
        primaryPhone:
          type: string
          description: Primary contact phone
        contacts:
          type: array
          items:
            type: integer
          description: Contact IDs only (no name, email, phone, etc.). The contacts must be created first via POST /contacts.
        custom:
          type: object
          additionalProperties:
            descr

# --- truncated at 32 KB (38 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/coperniq/refs/heads/main/openapi/coperniq-projects-api-openapi.yml