Welcome to the Coperniq API release notes. This section highlights noteworthy changes across endpoints, schemas, and docs.
Recent highlights
- New: Labels —
GET /labels(filter bytype),POST /labels,GET /labels/{labelId}.typeisWORK(work orders) orASSET. v2 mirrors these under/v2with the standard success envelope. - New: Assets —
GET /assets(filter byaccount_id),POST /assets,GET/PATCH /assets/{assetId}(setisArchived: truevia PATCH to archive). v2 mirrors these under/v2with the standard success envelope. - New: Invoice payments —
GET /invoices/{invoiceId}/payments,GET /invoices/{invoiceId}/payments/{paymentId}, andPOST /invoices/{invoiceId}/payments(optionalpaymentReferenceon create). - New: Quotes — full CRUD via
GET/POST /quotes,GET/PATCH/DELETE /quotes/{quoteId},GET /quotes/{quoteId}/pdf,POST /quotes/{quoteId}/send, andGET /opportunities/{opportunityId}/quotes. - New: Work order line items —
PUT /work-orders/{workOrderId}/line-itemsreplaces line items on service work orders (account type).GET /work-orders/{workOrderId}now includeslineItemswhen present. - New: Taxes —
GET /taxeslists company tax rates with pagination and archived filtering. - New: Bills — full CRUD for project bills via
GET/POST /bills,GET/PATCH/DELETE /bills/{billId}, andGET /projects/{projectId}/bills. Supports LINE_ITEMS and PERCENTAGE calculation methods. - Improvement: Nullable fields on
PATCH /projects/{projectId},PATCH /accounts/{accountId}, andPATCH /clients/{clientId}— passnullto clear a field (e.g.description,ownerId,primaryEmail) or any custom property.
Looking for a specific date? See the entries below.
Labels — list and create
Manage labels that can be applied to work orders and assets.
Endpoints
v2 exposes the same routes under the /v2 prefix with the standard { status, message, data } envelope.
Query parameters (GET /labels)
Create a label
name— required, non-empty string.type— required;WORKapplies the label to work orders,ASSETto assets. Note: the public API usesWORKwhere the internal system usesTASK.color— optional hex color code; passnullto create a label with no color.
Label object
Assets — list, create, read, update
Manage physical assets tied to a site and account. Reads use project-service GraphQL; creates and updates call fleet-service.
Endpoints
v2 exposes the same routes under the /v2 prefix with the standard { status, message, data } JSON envelope where applicable.
Query parameters (GET /assets)
Create body highlights
- Required:
accountId,siteId,type,manufacturer,model,serialNumber. - Optional:
status,labelIds, dates,description, image file ids,size,expectedLifetime.
PATCH notes
siteIdandaccountIdcannot be changed after creation; PATCH requests that include either field are rejected by request validation with400rather than being silently ignored.- Set
isArchived: trueto archive an asset, orisArchived: falseto unarchive it.
Invoice payments
New: List, get, and create payments on an invoice
You can list payments for an invoice, fetch a single payment by id, and record manual payments. Paths are scoped under the invoice (there is no global /payments resource).
v1 returns a JSON array for list, a single object for get-by-id, and the payment service payload for create (amounts in dollars on reads; create accepts dollars and converts to cents for core).
v2 (/v2/...) uses the same paths with the standard { status, message, data } envelope and dollar amounts on all responses.
Create a payment
Notes
paymentReferenceandnotesare optional.paymentMethodmust be one of:CASH,ACH,CREDIT_CARD,KLARNA,AFFIRM,CHECK.- Core does not expose
GET /payment-records/:id; get-by-id resolves the payment from the invoice’s nested payment records.
Quotes — full CRUD
You can now create, read, update, delete, send, and download PDF quotes through the public API.
Endpoints
Create a quote with sections
opportunityId is required. Provide line items either flat or grouped into named sections.
Business rules
opportunityIdis always required;workOrderIdis not accepted (usePUT /work-orders/{workOrderId}/line-itemsfor work order line items).- Each section must contain at least one line item (
lineItemsmin length 1). issueDatemay only be provided whenstatusisSENTorAPPROVED.discountTypemust bePERCENTAGEorFLATwhendiscountValueis 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.
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.
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.
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.
Query parameters
Project & opportunity title fallback
When a project or opportunity has no title of its own (empty string or whitespace-only), the API now returns the parent account’s title in the title field instead of the blank value.
This applies to all read endpoints that return project or opportunity records:
GET /projects,GET /projects/search,GET /projects/{projectId}GET /opportunities,GET /opportunities/search,GET /opportunities/{opportunityId}
Behavior
The underlying stored record is not modified — this is a read-time fallback only. Write endpoints (POST, PATCH) continue to accept and persist titles exactly as provided.
Why
Many integrations rely on title being a meaningful, human-readable label (list views, search results, downstream syncs). Projects that were created without a title were surfacing as blank rows, which was confusing. Falling back to the parent account’s title gives consumers a sensible default without changing the source of truth.
Bills
New: Bills endpoints
You can now create, read, update, and delete bills on projects via the public API.
Bills support two calculation methods:
LINE_ITEMS— itemised bill with one or more line items. Each line item requirescatalogItemId,quantity,unitCost(must be > 0), andunitPrice(may be negative for discounts).PERCENTAGE— percentage of the project’s base amount (0–100).
Create a LINE_ITEMS bill
Create a PERCENTAGE bill
Business rules
calculationMethodcannot be changed after creation.PERCENTAGEbills cannot haveissueDateorstatus.LINE_ITEMSbills: whenissueDateis provided,statusmust also be provided and must not beDRAFT.unitCostmust be greater than 0 for all line items.percentagemust be between 0 and 100.
Nullable fields on project, account, and client updates
Improvement: Clear fields by passing null
You can now explicitly clear nullable fields on projects, accounts, and clients by passing null in a PATCH request. Previously, null values were ignored and the existing value was left unchanged.
This applies to the following endpoints:
PATCH /projects/{projectId}PATCH /accounts/{accountId}PATCH /clients/{clientId}
Clearable fields
Custom properties (via the custom object) can also be cleared by passing null for any key.
Example
This will clear description, unassign the owner, and clear the pud_incentive custom property on the project.
Omitting a field entirely still leaves the existing value unchanged.
Work order notes and work items
New: Work order notes endpoints
You can now create and list notes directly on work orders.
Create a note
Response:
List notes
New: workItems on work order responses
GET /work-orders/{workOrderId} now includes a workItems array containing Blueprint workflow items linked to the work order. Two types are supported:
FORM— a form instance (e.g. site survey, roof mount checklist)FILE_REQUEST— a document upload request (e.g. shade report)
If no work items are linked, workItems is an empty array.
Sites endpoints
Full CRUD support for site records via the public API.
Sites are address/location records that belong to an account. A single account may have multiple sites.
Endpoints
Create a site
accountId is required. Either fullAddress or geoLocation must also be provided. The backend automatically geocodes fullAddress and checks for duplicate addresses — if a site with the same address already exists for the same account, the existing site is returned (200) instead of creating a duplicate.
List sites by account
Update a site
All fields are optional. Updating fullAddress triggers re-geocoding. To move a site to a different account, use POST /sites/{siteId}/move.
Move a site to a different account
Moves the site and all associated records to a different account. The original site is permanently deleted and a new site is created on the target account. ⚠️ This operation is irreversible.
Properties endpoint naming updates
GET /properties — new account and opportunity keys
The /properties response now includes account and opportunity keys in addition to the existing client and request keys:
The record_type query parameter now accepts account and opportunity as values:
Note:
clientandrequestare still accepted asrecord_typevalues and are still returned in the response for backwards compatibility. They will continue to work until all users have migrated to the new names.
Form template update endpoint
Update a form template
A new endpoint lets you update an existing form template:
PATCH /form-templates/{formTemplateId}— Update a form template’s name, property layout, assignee, collaborators, labels, and due date configuration.
All fields are optional — only provided fields are updated. formLayouts is optional — when provided, it fully replaces all layout groups and their fields; omit it to leave the existing layout untouched. Include existing groups with their id to preserve them, or omit the id for new groups. Groups not included are removed. Array order determines position on the form.
Fields within each group are set via the properties array, where each item specifies a type (TEXT, NUMERIC, DROPDOWN, or FILE) or references an existing project property via projectPropertyKey.
Note: Layout
idvalues (for groups and properties) are not stable — they change after every update. Always re-fetch the template viaGET /form-templates/{formTemplateId}to get current IDs before referencing them in a subsequent update.
Naming updates & new features
Object renames
Coperniq’s API terminology now matches the UI:
Existing /{resource}/{id}/comments paths are unchanged — no updates to existing integrations are required. A new unified PATCH /notes/{noteId} endpoint is also available. The renamed terms appear in operation names, tags, and SDK method names going forward.
Retrieve archived records
All GET list and get-by-ID endpoints for projects, opportunities, accounts, and workflows now support an include_archived query parameter.
By default (include_archived=false) only active records are returned — existing behavior is unchanged. Set include_archived=true to include archived records in the response.
Form template endpoints
Two new read-only endpoints let you retrieve form templates and their structure:
GET /form-templates— List all workflow form templates for your company.GET /form-templates/{formTemplateId}— Get a specific form template by ID, including its field definitions.
These are useful for dynamically building form submissions or inspecting available form structures before creating a form instance.
