> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.coperniq.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coperniq.io/_mcp/server.

## Account, Project & Opportunity contacts

### New: `isPrimary` and full contact detail

`contacts[]` on accounts, projects, and opportunities now returns `id`, `name`, `title`, `description`, `emails`, `phones`, and `isPrimary` for every contact (previously just `id`/`emails`/`phones` on accounts, and nothing at all on projects/opportunities).

* **`isPrimary`** is `true` for exactly one contact — the one at the lowest position (the first element you send on create/update). At most one contact is ever primary.
* **Projects and opportunities now return `contacts` too** — their own contacts, independent of and not inherited from the parent account's. Set them on create/update via the `contacts` request field, same as accounts. Pass `include_contacts=true` on `GET /projects`, `GET /projects/search`, `GET /projects/{project_id}`, and the equivalent `/opportunities` endpoints to include it — same as accounts.
* **`POST`/`PATCH` responses always include `contacts`** for accounts, projects, and opportunities — not gated behind `include_contacts` like `GET` is.

#### Notes

* Account create/update responses previously returned only `{ id }` for contacts immediately after a write — they now always return the full contact detail.

## Contact responses

### Fixed: missing fields

* `accounts`, `projects`, `opportunities`, and `vendors` — a contact's related records are now split into all four buckets. Previously only `accounts` and `projects` were populated; a contact linked to an opportunity or a vendor silently disappeared from the response.
* `PATCH /contacts/{contact_id}` previously could return empty `accounts`/`projects` even when the contact had existing links — it was trusting a raw write response that didn't include them. It now includes them after the write, matching `POST /contacts`.

## Projects & Opportunities

### Fixed: `workflowId` returning `null` after create/update

Creating or updating a project/opportunity with an explicit `workflowId` (Workflows 2.0) previously came back with `workflowId: null` in the response, even though the correct phase was assigned correctly. The re-fetch used after every create/update wasn't selecting the underlying field.

## Trades

### Updated: `trades` is now a documented enum

`trades` on projects and opportunities is validated against a fixed list of trade types (case-insensitive). The docs now show the full accepted list instead of a bare string, on both the request and response schemas.