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

# Authentication and scopes

> Create, protect, and scope Canary API keys

# Authentication and scopes

The Canary API authenticates every request with an organization API key. Send the key with the HTTP Bearer scheme.

```bash theme={"theme":"github-light"}
curl --fail-with-body "https://api.oncanary.com/v1/assets?limit=1" \
  --header "Authorization: Bearer $CANARY_API_KEY"
```

## Key prefixes and data access

| Prefix     |            Rate limit | Intended use                            |
| ---------- | --------------------: | --------------------------------------- |
| `sk_live_` | 1,000 requests/minute | Production integrations                 |
| `sk_test_` |   100 requests/minute | Development and lower-volume validation |

<Warning>
  Test and live keys access the same organization data. The prefix selects a rate-limit bucket. Use a dedicated Canary organization or clearly identified fixtures when development calls create, update, archive, or delete records.
</Warning>

## Create a key

1. As an organization administrator, open **Settings → API Keys** in Canary.
2. Select **Create API Key**.
3. Give the key a name that identifies its owner and workload.
4. Choose the test or live prefix.
5. Grant the smallest set of scopes required by the integration.
6. Copy the key into your secret manager when Canary displays it.

Canary stores a hash of the key and shows the complete secret once.

## Scope model

Every endpoint requires one exact scope. Read and write capabilities are separate: a write scope does not imply its read scope. Keys belong to one organization; an organization ID in a request cannot switch the key's tenant. API keys act as integration principals, not as the human user who created them. Human team membership and role presets do not replace API-key scopes.

### Work management

| Scope                        | Grants                                                                                                       |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `work_orders:read`           | List and read work orders                                                                                    |
| `work_orders:write`          | Create, update, and soft-delete work orders while retaining their history; approve requests into work orders |
| `work_requests:read`         | List work requests and read their attachments                                                                |
| `work_requests:write`        | Create, update, delete, and attach files to work requests                                                    |
| `work_request_portals:read`  | List and read request portal configurations                                                                  |
| `work_request_portals:write` | Create, update, and delete request portal configurations                                                     |

### Equipment and inventory

| Scope             | Grants                                                    |
| ----------------- | --------------------------------------------------------- |
| `assets:read`     | List and read assets                                      |
| `assets:write`    | Create and update assets                                  |
| `locations:read`  | List and read locations                                   |
| `locations:write` | Create and update locations                               |
| `parts:read`      | List and read parts                                       |
| `parts:write`     | Create and update parts; link or unlink parts from assets |
| `meters:read`     | List meters and readings                                  |
| `meters:write`    | Create, update, or archive meters; record readings        |

Linking or unlinking a part to an asset requires `parts:write`. Both resources must belong to the key's organization.

### Work-order parts and cost visibility

`GET /work-orders/{id}/parts` uses `work_orders:read`; its commands use `work_orders:write`. These are work-order operations, not direct inventory adjustment endpoints. Use the returned capabilities to determine allowed transitions and edits. Organization settings, lifecycle rules, and stock availability can still reject a command with the correct scope.

Work-order reads include their economic projection. `work_orders:read` therefore grants visibility of work-order labor rates, labor costs, and purchase costs; it is not a cost-redacted permission.

### Organization feature modules

Scopes do not enable disabled features. These module checks apply in addition to scopes and tenant checks:

| Public operation family                     | Required enabled module                                        |
| ------------------------------------------- | -------------------------------------------------------------- |
| Parts and asset–part links                  | Parts Inventory                                                |
| Meters and readings                         | Meters                                                         |
| Work requests, thumbnails, and attachments  | Requests                                                       |
| Work request portals                        | Request Portals                                                |
| Custom fields                               | The module associated with the target entity, where applicable |
| Identifier writes and target-specific lists | The module associated with the target entity, where applicable |

Identifier resolution filters unavailable targets. Retiring an identifier and archiving a meter remain available for cleanup after a module is disabled. Work-order parts retain history and expose service-computed capabilities for permitted recovery; a disabled module does not grant permission to create new stock commitments.

### Organization data

| Scope                 | Grants                                                        |
| --------------------- | ------------------------------------------------------------- |
| `identifiers:read`    | List identifiers and resolve scanned payloads                 |
| `identifiers:write`   | Attach, generate, import, and retire identifiers              |
| `custom_fields:read`  | List custom-field definitions                                 |
| `custom_fields:write` | Create, update, reorder, and archive custom-field definitions |

## Keep keys safe

* Store keys in a secret manager or protected environment variable.
* Create one key per integration and deployment environment.
* Keep keys out of source control, client-side applications, logs, URLs, and support screenshots.
* Rotate a key by creating its replacement, deploying the replacement, then revoking the previous key.
* Revoke a key immediately when its owner or workload changes unexpectedly.

## Authentication and authorization errors

Authentication errors use `application/problem+json` and include the same `X-Request-ID` value as the body `request_id`.

```json theme={"theme":"github-light"}
{
  "type": "https://api.oncanary.com/errors/invalid_api_key",
  "title": "Invalid API Key",
  "status": 401,
  "detail": "Invalid or expired API key",
  "request_id": "req_01JAY8FVDM6CH4R3X9Q2T7K5NP",
  "code": "invalid_api_key"
}
```

| Status | Code                           | Meaning                                                     |
| -----: | ------------------------------ | ----------------------------------------------------------- |
|    401 | `missing_authorization`        | The Authorization header is absent                          |
|    401 | `invalid_authorization_format` | The header uses an unsupported scheme or shape              |
|    401 | `invalid_api_key_format`       | The key has an unsupported prefix or shape                  |
|    401 | `invalid_api_key`              | The key is unknown, expired, or revoked                     |
|    403 | `insufficient_scope`           | The key lacks the operation's required scope                |
|    403 | `module_disabled`              | The required Canary module is disabled for the organization |

The generated endpoint reference displays each operation's required scope.

## Revoke a key

Open **Settings → API Keys**, select the key, and confirm revocation. Requests made with that key begin returning `401 invalid_api_key` immediately.
