Welcome to the Coperniq API release notes. This section highlights noteworthy changes across endpoints, schemas, and docs.

Recent highlights

  • New: AHJs — GET /ahjs (search, filter, and lat+lng geo lookup), GET /ahjs/{id}, and PATCH /ahjs/{id} to update custom property values. v2 mirrors these under /v2 with the standard success envelope.
  • Updated: GET /properties — now documents the ahj record type (custom AHJ properties only) and adds an isCustom boolean to every property to distinguish custom columns from built-in standard ones.
  • New: Sections — line items on projects, invoices, and bills can now be grouped into named sections (matching quotes and work orders); read responses expose sectionName per line item.
  • New: Vendors — full CRUD via GET/POST /vendors, GET/PATCH/DELETE /vendors/{vendorId}, GET /vendors/search, and many-to-many project linking via POST/DELETE /projects/{projectId}/vendors/{vendorId}. Vendor-specific fields: vendorType (enum), website, and projectIds.
  • New: Labels — GET /labels (filter by type), POST /labels, GET /labels/{labelId}. type is WORK (work orders) or ASSET. v2 mirrors these under /v2 with the standard success envelope.
  • New: Assets — GET /assets (filter by account_id), POST /assets, GET/PATCH /assets/{assetId} (set isArchived: true via PATCH to archive). v2 mirrors these under /v2 with the standard success envelope.

Looking for a specific date? See the entries below.

Quotes — full CRUD

You can now create, read, update, delete, send, and download PDF quotes through the public API.

Endpoints

MethodPathDescription
GET/quotesList all quotes (paginated, filterable by status and date)
GET/quotes/{quoteId}Get a quote by ID
GET/quotes/{quoteId}/pdfDownload a quote as PDF
GET/opportunities/{opportunityId}/quotesList quotes for an opportunity
POST/quotesCreate a quote on an opportunity
POST/quotes/{quoteId}/sendSend a quote to the customer
PATCH/quotes/{quoteId}Update a quote
DELETE/quotes/{quoteId}Delete a quote

Create a quote with sections

opportunityId is required. Provide line items either flat or grouped into named sections.

POST /quotes
1{
2 "opportunityId": 789225,
3 "sections": [
4 {
5 "name": "Materials",
6 "lineItems": [
7 {
8 "catalogItemId": 5884,
9 "quantity": 10,
10 "unitCost": 50,
11 "unitPrice": 75,
12 "name": "Solar Panel 400W"
13 }
14 ]
15 }
16 ],
17 "taxId": 12,
18 "discountType": "PERCENTAGE",
19 "discountValue": 5
20}

Business rules

  • opportunityId is always required; workOrderId is not accepted (use PUT /work-orders/{workOrderId}/line-items for work order line items).
  • Each section must contain at least one line item (lineItems min length 1).
  • issueDate may only be provided when status is SENT or APPROVED.
  • discountType must be PERCENTAGE or FLAT when discountValue is set.

Work order line items

New: PUT /work-orders/{workOrderId}/line-items

Replace all line items on a service work order’s underlying quote. If no quote exists yet, one is created automatically.

MethodPathDescription
PUT/work-orders/{workOrderId}/line-itemsReplace line items on a work order

This endpoint is only available for service work orders on an account (i.e. the parent project type is ACCOUNT). Calling it on a non-account work order returns 400.

PUT /work-orders/{workOrderId}/line-items
1{
2 "sections": [
3 {
4 "name": "Labor",
5 "lineItems": [
6 {
7 "catalogItemId": 5884,
8 "quantity": 4,
9 "unitCost": 75,
10 "unitPrice": 100,
11 "name": "Electrician — hourly"
12 }
13 ]
14 }
15 ]
16}

New: lineItems on GET /work-orders/{workOrderId}

The work order detail response now includes a lineItems array when the work order is a service work order on an account and has at least one line item. The property is omitted entirely when there are no line items or the work order is not on an account.

1{
2 "id": 2025433,
3 "title": "Install main panel",
4 "lineItems": [
5 {
6 "id": 8001,
7 "name": "Solar Panel 400W",
8 "description": null,
9 "quantity": 10,
10 "unitPrice": 75.00,
11 "totalPrice": 750.00,
12 "unit": "EACH"
13 }
14 ]
15}

List taxes

New: GET /taxes

List tax rates configured for your company. Use these IDs when assigning taxes to quotes, invoices, and other financial documents.

MethodPathDescription
GET/taxesList company taxes (paginated)
GET /taxes?page=1&page_size=20&include_archived=false
1[
2 {
3 "id": 42,
4 "name": "State Sales Tax",
5 "rate": "8.25",
6 "isArchived": false,
7 "createdAt": "2025-06-01T00:00:00.000Z",
8 "updatedAt": "2025-06-01T00:00:00.000Z"
9 }
10]

Query parameters

ParameterTypeDefaultDescription
include_archivedbooleanfalseInclude archived tax rates. Accepts true/false/1/0.
pageinteger1Page number
page_sizeinteger20Results per page (max 100)