Coperniq quotes API

The quotes API from Coperniq — 5 operation(s) for quotes.

OpenAPI Specification

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


        Supports:

        - Pagination (`page_size`, `page`)

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

        - Status filtering (`status`)

        - Sorting (`order_by`)

        '
      tags:
      - quotes
      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: order_by
        in: query
        description: Sort order for results
        required: false
        schema:
          $ref: '#/components/schemas/QuotesGetParametersOrderBy'
      - 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: status
        in: query
        description: Filter quotes by status
        required: false
        schema:
          $ref: '#/components/schemas/QuotesGetParametersStatus'
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: List of quotes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteListResponse'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListQuotesRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListQuotesRequestUnauthorizedError'
    post:
      operationId: create-quote
      summary: Create Quote
      description: 'Create a new quote on an opportunity (project/deal/account record).


        - `opportunityId`: Required — record ID used by the payment service.

        - `sections` or `lineItems`: At least one item required

        - `discountType` / `discountValue`: Optional discount

        - `taxId`: Optional tax

        - `issueDate` / `status`: `issueDate` only allowed with `status` of `SENT` or `APPROVED`


        To add or replace line items on a **work order**, use `PUT /work-orders/{workOrderId}/line-items` instead.

        '
      tags:
      - quotes
      parameters:
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '201':
          description: Quote created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateQuoteRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateQuoteRequestUnauthorizedError'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteCreate'
  /opportunities/{opportunityId}/quotes:
    get:
      operationId: get-opportunity-quotes
      summary: Get Opportunity Quotes
      description: Retrieve quotes for a specific opportunity.
      tags:
      - quotes
      parameters:
      - name: opportunityId
        in: path
        description: Opportunity ID
        required: true
        schema:
          type: integer
      - 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/OpportunitiesOpportunityIdQuotesGetParametersOrderBy'
      - 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: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: List of quotes for the opportunity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteListResponse'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetOpportunityQuotesRequestUnauthorizedError'
  /quotes/{quoteId}:
    get:
      operationId: get-quote
      summary: Get Quote
      description: Retrieve a specific quote by ID
      tags:
      - quotes
      parameters:
      - name: quoteId
        in: path
        required: true
        schema:
          type: string
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Quote details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetQuoteRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetQuoteRequestNotFoundError'
    patch:
      operationId: update-quote
      summary: Update Quote
      description: 'Update an existing quote. Supports partial updates.


        **`isArchived`**: pass `true` to archive or `false` to unarchive.


        When setting **`status`** to anything other than **`DRAFT`**, you must supply **`issueDate`** unless the quote already has one.


        **`sharedWithPortal`**: pass `true` or `false` to show or hide the quote on the client portal.

        '
      tags:
      - quotes
      parameters:
      - name: quoteId
        in: path
        required: true
        schema:
          type: string
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Quote updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateQuoteRequestBadRequestError'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateQuoteRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateQuoteRequestNotFoundError'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteUpdate'
    delete:
      operationId: delete-quote
      summary: Delete Quote
      description: 'Delete a quote. The quote is archived first (required by the payment service),

        then permanently deleted.

        '
      tags:
      - quotes
      parameters:
      - name: quoteId
        in: path
        required: true
        schema:
          type: string
      - 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/DeleteQuoteRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteQuoteRequestNotFoundError'
  /quotes/{quoteId}/pdf:
    get:
      operationId: get-quote-pdf
      summary: Get Quote PDF
      description: 'Returns the quote PDF. Response is JSON with base64-encoded PDF (`pdfBase64`) and `contentType`.

        '
      tags:
      - quotes
      parameters:
      - name: quoteId
        in: path
        required: true
        schema:
          type: string
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: PDF payload (base64 JSON)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quotes_getQuotePdf_Response_200'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetQuotePdfRequestUnauthorizedError'
        '403':
          description: API key valid but does not have access to this resource
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetQuotePdfRequestForbiddenError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetQuotePdfRequestNotFoundError'
  /quotes/{quoteId}/send:
    post:
      operationId: send-quote
      summary: Send Quote
      description: 'Email the quote to the customer and transition **DRAFT** to **SENT** when applicable.

        '
      tags:
      - quotes
      parameters:
      - name: quoteId
        in: path
        required: true
        schema:
          type: string
      - name: x-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Quote sent; returns the updated quote
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendQuoteRequestUnauthorizedError'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendQuoteRequestNotFoundError'
components:
  schemas:
    QuoteCreate:
      type: object
      properties:
        opportunityId:
          type: integer
          description: Opportunity / project / account record ID
        sections:
          type: array
          items:
            $ref: '#/components/schemas/QuoteSection'
          description: Grouped line items. Required if `lineItems` is not provided.
        lineItems:
          type: array
          items:
            $ref: '#/components/schemas/QuoteLineItemCreate'
          description: Flat line items (grouped into one section automatically). Required if `sections` is not provided.
        discountType:
          $ref: '#/components/schemas/QuoteCreateDiscountType'
          description: Discount type
        discountValue:
          type: number
          format: double
          description: Discount amount or percentage
        taxId:
          type: integer
          description: Tax configuration ID
        issueDate:
          type: string
          format: date-time
          description: Issue date. Requires `status` to be `SENT` or `APPROVED`.
        status:
          $ref: '#/components/schemas/QuoteCreateStatus'
          description: Initial status (defaults to DRAFT)
        description:
          type:
          - string
          - 'null'
        title:
          type: string
          description: Quote title (defaults to "Quote")
        servicePlanInstanceId:
          type: integer
        siteId:
          type: integer
      required:
      - opportunityId
      description: '`opportunityId` is the record (project/opportunity/account) id used by the payment service.


        When the quote is for a **Client (Account)** record, provide **`siteId`** (or use work-order line items via `PUT /work-orders/{workOrderId}/line-items`) so the quote can be linked correctly.

        '
      title: QuoteCreate
    QuotesGetParametersStatus:
      type: string
      enum:
      - DRAFT
      - SENT
      - APPROVED
      - CHANGES_REQUESTED
      - DECLINED
      title: QuotesGetParametersStatus
    ListQuotesRequestBadRequestError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesGetResponsesContentApplicationJsonSchemaCode'
        field:
          type: string
          description: Field that caused the validation error (if applicable)
      title: ListQuotesRequestBadRequestError
    QuoteSection:
      type: object
      properties:
        id:
          type: integer
          description: Section identifier
        name:
          type:
          - string
          - 'null'
          description: Section name (1–500 chars)
        lineItems:
          type: array
          items:
            $ref: '#/components/schemas/QuoteLineItemCreate'
          description: Line items within this section (at least one required)
      required:
      - lineItems
      title: QuoteSection
    QuotesGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - UNAUTHORIZED
      title: QuotesGetResponsesContentApplicationJsonSchemaCode
    GetQuotePdfRequestForbiddenError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPdfGetResponsesContentApplicationJsonSchemaCode'
      title: GetQuotePdfRequestForbiddenError
    GetQuotePdfRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPdfGetResponsesContentApplicationJsonSchemaCode'
      title: GetQuotePdfRequestUnauthorizedError
    QuoteRecord:
      type: object
      properties:
        id:
          type: integer
        title:
          type:
          - string
          - 'null'
        type:
          type:
          - string
          - 'null'
      title: QuoteRecord
    SendQuoteRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdSendPostResponsesContentApplicationJsonSchemaCode'
      title: SendQuoteRequestUnauthorizedError
    QuotesQuoteIdPdfGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: QuotesQuoteIdPdfGetResponsesContentApplicationJsonSchemaCode
    QuoteStatus:
      type: string
      enum:
      - DRAFT
      - SENT
      - APPROVED
      - CHANGES_REQUESTED
      - DECLINED
      description: Quote status
      title: QuoteStatus
    OpportunitiesOpportunityIdQuotesGetParametersOrderBy:
      type: string
      enum:
      - asc
      - desc
      default: asc
      title: OpportunitiesOpportunityIdQuotesGetParametersOrderBy
    QuoteListResponse:
      type: array
      items:
        $ref: '#/components/schemas/Quote'
      title: QuoteListResponse
    ListQuotesRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesGetResponsesContentApplicationJsonSchemaCode'
      title: ListQuotesRequestUnauthorizedError
    UpdateQuoteRequestBadRequestError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPatchResponsesContentApplicationJsonSchemaCode'
        field:
          type: string
          description: Field that caused the validation error (if applicable)
      title: UpdateQuoteRequestBadRequestError
    CreateQuoteRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesPostResponsesContentApplicationJsonSchemaCode'
      title: CreateQuoteRequestUnauthorizedError
    QuoteCreateStatus:
      type: string
      enum:
      - DRAFT
      - SENT
      - APPROVED
      - CHANGES_REQUESTED
      - DECLINED
      description: Initial status (defaults to DRAFT)
      title: QuoteCreateStatus
    QuoteUpdateStatus:
      type: string
      enum:
      - DRAFT
      - SENT
      - APPROVED
      - CHANGES_REQUESTED
      - DECLINED
      title: QuoteUpdateStatus
    SendQuoteRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdSendPostResponsesContentApplicationJsonSchemaCode'
      title: SendQuoteRequestNotFoundError
    GetOpportunityQuotesRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/OpportunitiesOpportunityIdQuotesGetResponsesContentApplicationJsonSchemaCode'
      title: GetOpportunityQuotesRequestUnauthorizedError
    QuoteLineItemCreate:
      type: object
      properties:
        id:
          type: integer
          description: Existing line item ID (omit for new items)
        catalogItemId:
          type: integer
          description: Catalog item identifier
        quantity:
          type: integer
          description: Quantity
        unitCost:
          type: number
          format: double
          description: Cost per unit (dollars, cent precision)
        unitPrice:
          type: number
          format: double
          description: Price per unit (dollars, must be positive with cent precision)
        description:
          type:
          - string
          - 'null'
          description: Line item description
      required:
      - catalogItemId
      - quantity
      - unitCost
      - unitPrice
      title: QuoteLineItemCreate
    QuoteLineItemCatalogItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        sku:
          type:
          - string
          - 'null'
        type:
          type:
          - string
          - 'null'
        manufacturer:
          type:
          - string
          - 'null'
      title: QuoteLineItemCatalogItem
    UpdateQuoteRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPatchResponsesContentApplicationJsonSchemaCode'
      title: UpdateQuoteRequestNotFoundError
    QuoteCreateDiscountType:
      type: string
      enum:
      - PERCENTAGE
      - FIXED
      description: Discount type
      title: QuoteCreateDiscountType
    OpportunitiesOpportunityIdQuotesGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - UNAUTHORIZED
      title: OpportunitiesOpportunityIdQuotesGetResponsesContentApplicationJsonSchemaCode
    Quote:
      type: object
      properties:
        id:
          type: integer
          description: Quote identifier
        quoteNumber:
          type:
          - integer
          - 'null'
          description: Unique quote number (uid)
        description:
          type:
          - string
          - 'null'
          description: Quote description
        status:
          $ref: '#/components/schemas/QuoteStatus'
          description: Quote status
        amount:
          type: number
          format: double
          description: Total quote amount (dollars)
        discountType:
          oneOf:
          - $ref: '#/components/schemas/QuoteDiscountType'
          - type: 'null'
          description: Discount type
        discountValue:
          type:
          - number
          - 'null'
          format: double
          description: Discount amount or percentage value
        taxId:
          type:
          - integer
          - 'null'
          description: Tax configuration ID
        issueDate:
          type:
          - string
          - 'null'
          format: date-time
          description: Issue date when the quote has been issued
        subtotal:
          type:
          - number
          - 'null'
          format: double
          description: Subtotal in dollars (before tax)
        taxRate:
          type:
          - number
          - 'null'
          format: double
          description: Applied tax rate
        isArchived:
          type: boolean
          description: Whether the quote is archived
        sharedWithPortal:
          type: boolean
          description: Whether the quote is shared with the client portal
        createdAt:
          type: string
          format: date-time
          description: Creation timestamp
        updatedAt:
          type: string
          format: date-time
          description: Last update timestamp
        account:
          oneOf:
          - $ref: '#/components/schemas/QuoteAccount'
          - type: 'null'
        record:
          oneOf:
          - $ref: '#/components/schemas/QuoteRecord'
          - type: 'null'
        lineItems:
          type: array
          items:
            $ref: '#/components/schemas/QuoteLineItem'
      required:
      - id
      - status
      - amount
      - createdAt
      - updatedAt
      title: Quote
    GetQuotePdfRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPdfGetResponsesContentApplicationJsonSchemaCode'
      title: GetQuotePdfRequestNotFoundError
    Quotes_getQuotePdf_Response_200:
      type: object
      properties:
        pdfBase64:
          type: string
        contentType:
          type: string
      title: Quotes_getQuotePdf_Response_200
    QuotesQuoteIdDeleteResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: QuotesQuoteIdDeleteResponsesContentApplicationJsonSchemaCode
    QuoteLineItem:
      type: object
      properties:
        id:
          type: integer
          description: Line item identifier
        quantity:
          type: integer
          description: Quantity
        description:
          type:
          - string
          - 'null'
          description: Line item description
        unitCost:
          type: number
          format: double
          description: Cost per unit (dollars)
        totalCost:
          type: number
          format: double
          description: Total cost (dollars)
        unitPrice:
          type: number
          format: double
          description: Price per unit (dollars)
        totalPrice:
          type: number
          format: double
          description: Total price (dollars)
        sectionName:
          type:
          - string
          - 'null'
          description: Line item section name; null when the item is ungrouped
        catalogItem:
          oneOf:
          - $ref: '#/components/schemas/QuoteLineItemCatalogItem'
          - type: 'null'
      required:
      - id
      - quantity
      - unitCost
      - unitPrice
      title: QuoteLineItem
    QuotesQuoteIdSendPostResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: QuotesQuoteIdSendPostResponsesContentApplicationJsonSchemaCode
    UpdateQuoteRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdPatchResponsesContentApplicationJsonSchemaCode'
      title: UpdateQuoteRequestUnauthorizedError
    CreateQuoteRequestBadRequestError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesPostResponsesContentApplicationJsonSchemaCode'
        field:
          type: string
          description: Field that caused the validation error (if applicable)
      title: CreateQuoteRequestBadRequestError
    QuoteUpdate:
      type: object
      properties:
        sections:
          type: array
          items:
            $ref: '#/components/schemas/QuoteSection'
        lineItems:
          type: array
          items:
            $ref: '#/components/schemas/QuoteLineItemCreate'
        discountType:
          $ref: '#/components/schemas/QuoteUpdateDiscountType'
        discountValue:
          type: number
          format: double
        taxId:
          type:
          - integer
          - 'null'
        issueDate:
          type: string
          format: date-time
        status:
          $ref: '#/components/schemas/QuoteUpdateStatus'
        description:
          type:
          - string
          - 'null'
        sharedWithPortal:
          type: boolean
          description: When true, the quote is visible on the client portal; when false, it is hidden.
        isArchived:
          type: boolean
          description: Set true to archive or false to unarchive (maps to payment service archive/unarchive routes)
      title: QuoteUpdate
    QuoteDiscountType:
      type: string
      enum:
      - PERCENTAGE
      - FIXED
      description: Discount type
      title: QuoteDiscountType
    QuotesQuoteIdPatchResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: QuotesQuoteIdPatchResponsesContentApplicationJsonSchemaCode
    GetQuoteRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdGetResponsesContentApplicationJsonSchemaCode'
      title: GetQuoteRequestUnauthorizedError
    QuoteAccount:
      type: object
      properties:
        id:
          type: integer
        title:
          type:
          - string
          - 'null'
      title: QuoteAccount
    DeleteQuoteRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdDeleteResponsesContentApplicationJsonSchemaCode'
      title: DeleteQuoteRequestNotFoundError
    QuotesPostResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - UNAUTHORIZED
      title: QuotesPostResponsesContentApplicationJsonSchemaCode
    GetQuoteRequestNotFoundError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdGetResponsesContentApplicationJsonSchemaCode'
      title: GetQuoteRequestNotFoundError
    QuoteUpdateDiscountType:
      type: string
      enum:
      - PERCENTAGE
      - FIXED
      title: QuoteUpdateDiscountType
    DeleteQuoteRequestUnauthorizedError:
      type: object
      properties:
        message:
          type: string
        code:
          $ref: '#/components/schemas/QuotesQuoteIdDeleteResponsesContentApplicationJsonSchemaCode'
      title: DeleteQuoteRequestUnauthorizedError
    QuotesQuoteIdGetResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
      - NOT_FOUND
      title: QuotesQuoteIdGetResponsesContentApplicationJsonSchemaCode
    QuotesGetParametersOrderBy:
      type: string
      enum:
      - asc
      - desc
      default: asc
      title: QuotesGetParametersOrderBy
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic