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

Recent highlights

  • New: Object naming aligned with Coperniq UI — clients are now accounts, requests are now opportunities, and comments are now notes.
  • New: Retrieve archived records by passing include_archived=true on any GET list or get-by-ID endpoint for projects, opportunities, accounts, and workflows.
  • New: Form template endpoints — GET /form-templates and GET /form-templates/{formTemplateId} — let you retrieve workflow templates and their structure.
  • New: PATCH /form-templates/{formTemplateId} — update a form template’s name, layout, assignee, collaborators, labels, and due date configuration.
  • New: Streamed file uploads for projects and opportunities with binary-safe handling

Documentation updates

  • Clarified file upload usage, binary limits, and recommended large-file approach
  • Documented full TradeGroup, ProductCategory, and ServiceCategory enums for catalog items and wired them into the public schemas.

Looking for a specific date? See the entries below.

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 id values (for groups and properties) are not stable — they change after every update. Always re-fetch the template via GET /form-templates/{formTemplateId} to get current IDs before referencing them in a subsequent update.

PATCH /form-templates/{formTemplateId}
1{
2 "name": "Site Inspection Checklist",
3 "formLayouts": [
4 {
5 "name": "Site Details",
6 "properties": [
7 { "projectPropertyKey": "site_address" },
8 { "type": "TEXT", "name": "Inspector Notes", "isRequired": false }
9 ]
10 }
11 ],
12 "assigneeProperty": "OWNER",
13 "dueDateXDaysAfter": 7
14}

Naming updates & new features

Object renames

Coperniq’s API terminology now matches the UI:

Old nameNew nameEndpoints
ClientsAccounts/accounts, /accounts/{accountId}
RequestsOpportunities/opportunities, /opportunities/{opportunityId}
CommentsNotes/{resource}/{id}/comments (unchanged); new PATCH /notes/{noteId}

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.

GET /projects?include_archived=true
GET /opportunities?include_archived=true
GET /accounts?include_archived=true
GET /workflows?include_archived=true

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.


Forms: update & attach files by URL

What’s new?

  • New PATCH /forms/{formId} endpoint lets you update a form’s core fields and responses in one call (status, due dates, collaborators, and individual field values).
  • New POST /forms/{formId}/fields/file-from-url endpoint uploads a file from a public URL and attaches it to a specific FILE-type form field.

Impact

  • Form updates can now be performed via the public API.
  • Integrations can push external documents (e.g. generated PDFs, reports, photos) directly into form fields using a simple URL-based workflow.

Catalog items: new categories & trade groups

What’s new?

  • Catalog items are now backed by typed categories and trade groups:
    • category uses Product/Service categories (e.g., PV_MODULE, BATTERY_SYSTEM, INSTALLATION, MAINTENANCE).
    • tradeGroup is an enum (ENERGY, MECHANICAL, ELECTRICAL, PLUMBING, LOW_VOLTAGE, ENVELOPE, OTHER).
  • The GET /catalog-items endpoint now returns a flat list of catalog items instead of nested catalogs.
  • POST /catalog-items and PATCH /catalog-items/{catalogItemId} validate payloads against the new category + tradeGroup rules.

Impact

  • Generated docs show complete dropdowns for tradeGroup and category, making catalog item creation and updates easier and safer.

File uploads: streaming support, reliability fixes, and limits

What’s new?

  • Streamed multipart uploads for files:
    • POST /projects/{projectId}/files/upload
    • POST /requests/{requestId}/files/upload
  • You can provide phaseInstanceId either as a form field or as a ?phaseInstanceId= query parameter; the API will include it once in the forwarded payload.

Fixes and improvements

  • Robust parsing: files are fully consumed when building the outgoing multipart/form-data.
  • Getting a project returns the project manager data.
  • Allow files to be added in a certain project or request phase.

Usage notes

  • Send multipart/form-data with a file part; optional fields may include phaseInstanceId.
  • For non‑multipart uploads, send the raw bytes as the request body and pass filename/content type via:
    • Headers X-File-Name and X-File-Content-Type (case‑insensitive), or
    • Query params name and content_type.

Platform limits

  • The API enforces a 10 MB request limit. With base64 encoding and multipart overhead, practical max payload is ~6–7 MB.
  • For larger uploads, use an out‑of‑band approach (e.g., presigned upload) and then create the file record by URL.

Compatibility

  • No response shape changes. Successful uploads return: id, name, downloadUrl, type, updatedAt, createdAt, companyId, metaData, source, createdByUser, isArchived.

Projects search endpoint

What’s new?

  • Added GET /projects/search to query projects using up to two filters joined by logic (and/or).
  • Supports standard fields (e.g., status, title, city, type, numeric/datetime fields) and custom properties by key name.
  • Operators: eq, neq, gt, gte, lt, lte, contains, in, nin, between, exists.
  • Pagination and sorting supported via page_size, page, and order_by.

Parameters

  • prop1, op1, value1 (required)
  • prop2, op2, value2 (optional)
  • logic: and | or (default and)
  • page_size, page, order_by

Value formats

  • in/nin lists:
    • Plain CSV: value1=ACTIVE,ON_HOLD
    • Quoted CSV (values with commas): value1="Last, First",Other
    • JSON array: value1=["Last, First","Other"]
  • between ranges:
    • Dates: value1=2025-01-01,2025-12-31
    • Numbers: value1=10000,50000

Examples

  • Status equals ACTIVE:
    • GET /v1/projects/search?prop1=status&op1=eq&value1=ACTIVE
  • Title contains “Solar”:
    • GET /v1/projects/search?prop1=name&op1=contains&value1=Solar
  • Status IN (ACTIVE, ON_HOLD) AND city = Austin:
    • GET /v1/projects/search?prop1=status&op1=in&value1=ACTIVE,ON_HOLD&logic=and&prop2=city&op2=eq&value2=Austin
  • Custom multiselect includes any of [“1”, “Option, with a comma”]:
    • GET /v1/projects/search?prop1=custom_multiselect&op1=in&value1=["1","Option, with a comma"]
  • Updated within 2025:
    • GET /v1/projects/search?prop1=updatedAt&op1=between&value1=2025-01-01,2025-12-31

Summary

Today’s release adds request/client work order endpoints, consolidates visit schemas, and completes the comments API across projects/requests/clients. We also improved the docs’ structure and fixed operation IDs for navigation.

What’s new?

  • Request Work Orders: List, create, and update request work orders.
  • Client Work Orders: List and create client work orders.
  • Comments API: List/create/update/delete comments for projects, requests, and clients.

Changes

  • Work Orders
    • POST /projects/{projectId}/work-orders requires templateId and accepts optional phaseInstanceId (phase must be started when provided).
    • POST /requests/{requestId}/work-orders requires templateId, optional phaseInstanceId (phase doesn’t need to be started).
    • POST /clients/{clientId}/work-orders requires templateId (no phases).
    • GET /requests/{requestId}/work-orders lists request work orders.
    • PATCH /requests/{requestId}/work-orders/{workOrderId} updates a request work order.
  • Comments
    • Projects: GET /projects/{projectId}/comments, POST /projects/{projectId}/comments, PATCH /projects/{projectId}/comment/{commentId}, DELETE /projects/{projectId}/comment/{commentId}.
    • Requests: GET /requests/{requestId}/comments, POST /requests/{requestId}/comments, PATCH /requests/{requestId}/comment/{commentId}, DELETE /requests/{requestId}/comment/{commentId}.
    • Clients: GET /clients/{clientId}/comments, POST /clients/{clientId}/comments, PATCH /clients/{clientId}/comment/{commentId}, DELETE /clients/{clientId}/comment/{commentId}.
  • Projects
    • GET /projects/{projectId} includes phaseInstances array (phase data).
  • Requests
    • GET /requests/{requestId} includes phaseInstances array (phase data).
  • Catalog Items
    • Cleaned up examples and aligned schemas with public shape.

Notes

  • For project work order creation, when phaseInstanceId is provided, the phase must already be started.
  • Request work order creation does not require a started phase.

Today’s release focuses on improving Work Orders creation, tightening schemas, and cleaning up the docs.

What’s new?

  • Create Work Order: You can now create a work order under a specific phase instance using templateId and phaseInstanceId. The response includes id, createdAt, updatedAt, description, position, phaseInstanceId, projectId, and createdById.
  • Full CRUD on Catalog Items: You can now, get, create, update, and delete catalog items in your company settings.
  • Form Retrieval: You can now get forms on a project and get form details.
  • Project Phase Instances: Getting a project by ID now includes the phase instances for that project.

Changes

  • Work Orders
    • POST /projects/{projectId}/work-orders requires templateId and phaseInstanceId.
  • Catalogs & Catalog Items
    • GET /catalog-items returns catalogs with their catalog items.
    • GET /catalog-items/{catalogItemId} returns a catalog item.
    • POST /catalog-items creates a catalog item.
    • PATCH /catalog-items/{catalogItemId} updates a catalog item.
  • Forms
    • GET /projects/{projectId}/forms returns a list of the forms on a project.
    • GET /forms/{formId} returns the form details, including field values.
  • Projects
    • GET /projects/{projectId} includes an array of phaseInstances.

Notes

  • The provided phaseInstanceId must belong to the project where the work order is created.