Coperniq quotes API
The quotes API from Coperniq — 5 operation(s) for quotes.
The quotes API from Coperniq — 5 operation(s) for quotes.
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