> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oncanary.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Resource model

> How public Canary resources connect and which lifecycle rules integrations should preserve

# Resource model

Canary organizes maintenance around work, equipment context, measurements, inventory, and organization-defined data.

## Relationship map

| Resource     | Connects to                                             | Integration role                                |
| ------------ | ------------------------------------------------------- | ----------------------------------------------- |
| Work request | Asset, location, approver team, attachments, work order | Capture and review a reported need              |
| Work order   | Asset, location, assignee, request                      | Plan and track maintenance work                 |
| Asset        | Location, parent asset, organization asset types, parts | Represent equipment and its operational context |
| Location     | Parent location and direct child locations              | Organize physical places                        |
| Meter        | Exactly one asset or location; many readings            | Track usage or observed values                  |
| Part         | Asset links and a part type                             | Represent a spare or consumable record          |
| Identifier   | Exactly one asset, location, or part                    | Resolve a scanner payload to a resource         |
| Custom field | Asset, location, part, or work-order resource family    | Add organization-defined values                 |

## Work requests and work orders

Work requests use the MaintainX-compatible wire style. Their public status vocabulary is `PENDING`, `REJECTED`, `APPROVED`, and `DONE`. Internally canceled requests stay outside this compatibility surface.

Create a native work order with `workRequestId` to approve a pending request and link the resulting work order in one operation:

```json theme={"theme":"github-light"}
{
  "title": "Inspect reported leak",
  "priority": "high",
  "workRequestId": "01JAY9XWBQ3R2H7V5F6N8K4MCP"
}
```

A replay with the same request returns its existing linked work order. A rejected request returns `409 invalid_work_request_state`.

The compatibility `/workorders` adapter uses uppercase types and priorities. Priority mappings preserve its narrower vocabulary: `NONE` creates Canary priority `medium`, and Canary `critical` reads as compatibility `HIGH`.

`DELETE /work-orders/{id}` soft-deletes the record and preserves its maintenance history, costs, procedure results, and audit evidence. Deleted work orders disappear from public reads, and chain fields such as `previous_id` or `next_id` become `null` when their linked record is unavailable. Repeating the same delete returns `204 No Content`.

## Assets and locations

Asset `status` values are `online`, `offline`, and `not_monitored`. Asset `criticality` values are `critical`, `important`, and `normal`.

`asset_type` is Canary's built-in classification (`equipment`, `vehicle`, or `facility`). `asset_types` is a read-only array of organization-defined type assignments. Asset hierarchy fields are also read-only in public v1:

* `parent_asset_id` identifies the direct parent.
* `sub_asset_count` counts active descendants.

Locations expose `parentId` on reads and writes. Location detail includes `childrenIds`. The current hierarchy supports one parent/sub-location level and rejects invalid moves with `409 invalid_location_hierarchy`.

## Meters and readings

A new meter must reference exactly one `asset_id` or `location_id`. Readings are immutable time-series observations ordered by `reading_at` and ID.

`DELETE /meters/{id}` archives an active meter. Existing readings are preserved. A meter referenced by an automation returns `409 resource_in_use` until the dependency is removed.

## Parts and asset links

Parts are master records. Link and unlink them through `/assets/{id}/parts/{partId}`. Both operations require `parts:write`, and both resources must belong to the key's organization.

The public Part resource describes the part record and minimum-stock setting. Direct inventory adjustment endpoints are outside public v1. Work-order consumption is available through `/work-orders/{id}/parts`.

### Work-order parts

`GET /work-orders/{id}/parts` requires `work_orders:read` and returns the section object directly, including rows, `partStatus`, server-computed capabilities, and `aggregateVersion`.

`POST /work-orders/{id}/parts` requires `work_orders:write`. Send a new `idempotencyKey` and the last-read `expectedAggregateVersion` with each command. Retry an uncertain response with the identical command and key. Refetch after a `409` conflict.

* `operation: "transition"` takes `targetStatus`: `assigned`, `reserved`, `kitted`, `staged`, or `issued`. Follow `capabilities.allowedTransitions`; staging settings may hide statuses.
* `operation: "replace"` takes the complete desired `items` array (`id`, `partId`, `locationId`, positive integer `quantity`, optional `unitCostMinor`). Retain row IDs when editing; omit rows to remove them. Cost overrides require the organization setting and an authorized caller.

Assigned parts do not reserve stock. Reserved, Kitted, and Staged contribute to committed quantity. Issued deducts stock immediately; completion also issues pending parts. Editing issued usage adjusts stock by the difference, including on completed work orders. Returning an active work order's parts from Issued to Assigned returns its effective used quantity. Reopening a work order preserves Issued status. Original stock movements remain in history alongside corrections.

## Custom fields

Custom-field definition routes use plural compatibility entity names: `assets`, `locations`, `parts`, and `workOrders`.

Entity writes accept `extraFields` as an object keyed by the visible field label:

```json theme={"theme":"github-light"}
{
  "name": "North compressor",
  "asset_type": "equipment",
  "extraFields": {
    "Vendor account": "ACME-1042"
  }
}
```

Detail responses include `extraFields`. Asset, part, and native work-order lists omit those values; location lists include them when `expand=extra_fields` is requested.

## Identifiers

Identifiers are organization-scoped mappings from exact scanner payloads to assets, locations, or parts. Canary-generated values and customer-owned values share the same resolver. See [Identifiers](/guides/identifiers) for attach, generate, import, and resolution workflows.
