> 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.

# Webhooks | Coperniq API

> Receive real-time event notifications from Coperniq via webhooks. Set up outbound webhooks for projects, work orders, appointments, and more.

## Webhooks

Coperniq can send real-time notifications to your server whenever events occur — a project is created, a work order is completed, a phase starts, and more. These outbound webhooks are powered by Coperniq's Automation engine.

> **Note:** Webhooks are configured in the Coperniq UI, not via the API. See [How to Set Up Outbound Webhooks](https://support.coperniq.io/articles/7599634208-how-to-setup-outboudn-webhooks-with-coperniq-automations) for the full setup walkthrough.

## Setup

1. Navigate to **Company Settings → Process Studio → Automations**
2. Click **+ AUTOMATION** and give it a name
3. Configure your **Trigger** (the event that fires the webhook)
4. Set the **Action** to **Call webhook** and enter your endpoint URL
5. Toggle the automation **Active** and save

**Requirements for your endpoint:**

* Must accept `POST` requests with `Content-Type: application/json`
* No authentication is required
* Return any `2xx` status to acknowledge receipt — any other status triggers a retry

> Webhooks only fire for records that meet the trigger criteria **after** the automation is activated. Records created before activation are not processed retroactively.

## Payload structure

Every webhook is a `POST` request with a JSON body containing up to three top-level keys:

| Key         | Type   | When present                                                       |
| ----------- | ------ | ------------------------------------------------------------------ |
| `event`     | object | Always                                                             |
| `record`    | object | When the trigger is associated with a Project, Request, or Account |
| `workOrder` | object | Work order triggers only                                           |

### event

Always present. Contains metadata about what triggered the webhook.

| Field         | Type     | Description                                                     |
| ------------- | -------- | --------------------------------------------------------------- |
| `eventId`     | number   | Unique ID for this event                                        |
| `recordId`    | number   | ID of the associated record                                     |
| `triggerKey`  | string   | Machine-readable trigger identifier (see [Triggers](#triggers)) |
| `triggerName` | string   | Human-readable trigger name                                     |
| `firedAt`     | datetime | ISO 8601 timestamp of when the event fired                      |

Trigger-specific fields are added to `event` depending on the trigger type. See [Triggers](#triggers) for the full list.

### record

Present when the trigger is associated with a Project, Request, or Account.

| Field           | Type                 | Description                                       |
| --------------- | -------------------- | ------------------------------------------------- |
| `id`            | number               | Record ID                                         |
| `uid`           | number               | Human-readable record number                      |
| `type`          | string               | `"PROJECT"`, `"DEAL"`, `"ACCOUNT"`, or `"VENDOR"` |
| `title`         | string               | Record title                                      |
| `status`        | string \| null       | Project or account status                         |
| `requestStatus` | string \| null       | Opportunity status                                |
| `stage`         | `{id, name}` \| null | Current workflow stage                            |
| `address`       | string \| null       | Primary address                                   |
| `city`          | string \| null       | City                                              |
| `state`         | string \| null       | State                                             |
| `geoLocation`   | object \| null       | Lat/lng coordinates                               |
| `jurisdiction`  | `{id, name}` \| null | Jurisdiction                                      |
| `trades`        | string\[] \| null    | Trades associated with the record                 |
| `dealValue`     | number \| null       | Project or opportunity value                      |
| `ownerId`       | number \| null       | ID of the assigned owner                          |
| `primaryEmail`  | string \| null       | Primary contact email                             |
| `primaryPhone`  | string \| null       | Primary contact phone                             |
| `createdAt`     | datetime             | ISO 8601 creation timestamp                       |
| `updatedAt`     | datetime             | ISO 8601 last-updated timestamp                   |

### workOrder

Present only for work order triggers.

| Field             | Type             | Description                        |
| ----------------- | ---------------- | ---------------------------------- |
| `id`              | number           | Work order ID                      |
| `uid`             | number           | Human-readable work order number   |
| `title`           | string           | Work order title                   |
| `description`     | string \| null   | Work order description             |
| `status`          | string           | Current status                     |
| `priority`        | number \| null   | Priority level                     |
| `recordId`        | number           | ID of the parent record            |
| `assigneeId`      | number \| null   | ID of the assigned user            |
| `isField`         | boolean          | Whether this is a field work order |
| `startDate`       | datetime \| null | Scheduled start                    |
| `endDate`         | datetime \| null | Scheduled end                      |
| `startDateAllDay` | boolean          | Whether start date is all-day      |
| `endDateAllDay`   | boolean          | Whether end date is all-day        |
| `completionDate`  | datetime \| null | Actual completion date             |
| `createdAt`       | datetime         | ISO 8601 creation timestamp        |
| `modifiedAt`      | datetime         | ISO 8601 last-modified timestamp   |

## Triggers

The `triggerKey` in the `event` object identifies which event fired. Some triggers add extra fields to `event` beyond the base set.

### Work order triggers

| `triggerKey`           | Description                        | Extra `event` fields                             |
| ---------------------- | ---------------------------------- | ------------------------------------------------ |
| `TASK_CREATED`         | A work order was created           | `workOrderId`, `currentStatus`, `previousStatus` |
| `TASK_COMPLETED`       | A work order was completed         | `workOrderId`                                    |
| `TASK_STATUS_MOVEMENT` | A work order moved to a new status | `workOrderId`, `currentStatus`, `previousStatus` |

### Record triggers

| `triggerKey`               | Description                           | Extra `event` fields |
| -------------------------- | ------------------------------------- | -------------------- |
| `PROJECT_CREATED`          | A project was created                 | —                    |
| `REQUEST_CREATED`          | A request was created                 | —                    |
| `PROJECT_STATUS_MOVEMENT`  | A project moved to a new status       | —                    |
| `DEAL_STATUS_MOVEMENT`     | A request moved to a new status       | —                    |
| `PROJECT_PROPERTY_UPDATED` | A project custom property was updated | —                    |
| `DEAL_PROPERTY_UPDATED`    | A request custom property was updated | —                    |
| `CALL_UPSERTED`            | A call was logged or updated          | —                    |

### Phase triggers

| `triggerKey`              | Description                   | Extra `event` fields                                        |
| ------------------------- | ----------------------------- | ----------------------------------------------------------- |
| `PROJECT_PHASE_STARTED`   | A project entered a new phase | `phaseInstanceId`, `phaseTemplateId`, `phaseType`, `status` |
| `PROJECT_PHASE_COMPLETED` | A project phase was completed | `phaseInstanceId`, `phaseTemplateId`, `phaseType`, `status` |
| `REQUEST_PHASE_STARTED`   | A request entered a new phase | `phaseInstanceId`, `phaseTemplateId`, `phaseType`, `status` |
| `REQUEST_PHASE_COMPLETED` | A request phase was completed | `phaseInstanceId`, `phaseTemplateId`, `phaseType`, `status` |

### SLA triggers

| `triggerKey`                  | Description                      | Extra `event` fields                      |
| ----------------------------- | -------------------------------- | ----------------------------------------- |
| `PROJECT_PHASE_SLA_VIOLATION` | A project phase exceeded its SLA | `overdueAt`, `slaType`, `phaseTemplateId` |
| `DEAL_PHASE_SLA_VIOLATION`    | A request phase exceeded its SLA | `overdueAt`, `slaType`, `phaseTemplateId` |

### Appointment triggers

| `triggerKey`              | Description                    | Extra `event` fields                          |
| ------------------------- | ------------------------------ | --------------------------------------------- |
| `APPOINTMENT_CREATED`     | An appointment was scheduled   | `appointmentId`, `dueDate`                    |
| `APPOINTMENT_RESCHEDULED` | An appointment was rescheduled | `appointmentId`, `dueDate`, `previousDueDate` |

## Example payload

```json
{
  "event": {
    "eventId": 48291,
    "recordId": 10423,
    "triggerKey": "TASK_STATUS_MOVEMENT",
    "triggerName": "Work Order Status Movement",
    "firedAt": "2026-03-31T17:04:22.000Z",
    "workOrderId": 8812,
    "currentStatus": "COMPLETED",
    "previousStatus": "IN_PROGRESS"
  },
  "record": {
    "id": 10423,
    "uid": 3301,
    "type": "PROJECT",
    "title": "123 Main St Austin TX 78701",
    "status": "ACTIVE",
    "requestStatus": null,
    "stage": { "id": 16651, "name": "Installation" },
    "address": "123 Main St Austin TX 78701",
    "city": "Austin",
    "state": "TX",
    "geoLocation": { "lat": 30.2672, "lng": -97.7431 },
    "jurisdiction": null,
    "trades": ["Solar", "Storage"],
    "dealValue": 28500,
    "ownerId": 13870,
    "primaryEmail": "homeowner@example.com",
    "primaryPhone": "+15125550100",
    "createdAt": "2026-01-15T14:30:00.000Z",
    "updatedAt": "2026-03-31T17:04:22.000Z"
  },
  "workOrder": {
    "id": 8812,
    "uid": 204,
    "title": "Panel Installation",
    "description": null,
    "status": "COMPLETED",
    "priority": null,
    "recordId": 10423,
    "assigneeId": 13870,
    "isField": true,
    "startDate": "2026-03-31T08:00:00.000Z",
    "endDate": "2026-03-31T17:00:00.000Z",
    "startDateAllDay": false,
    "endDateAllDay": false,
    "completionDate": "2026-03-31T17:04:22.000Z",
    "createdAt": "2026-03-01T09:00:00.000Z",
    "modifiedAt": "2026-03-31T17:04:22.000Z"
  }
}
```