# Operations · Management API

> Management API reference for operations: GET /operations/{id}.

> Markdown version of https://kanorio.com/en/developers/management-api/operations. Append `.md` to any developer docs URL for this format. Index: https://kanorio.com/llms.txt · MCP: https://app.kanorio.com/api/mcp

Base URL: `https://app.kanorio.com/api/v1` · [Errors](https://kanorio.com/en/developers/basics/errors) · [Pagination](https://kanorio.com/en/developers/basics/pagination)

### Retrieve an operation

`GET /operations/{id}`

- Stability: beta
- Permission: `console:view`
- Rate limit: default (120/minute per token)
- MCP tool: `operations_get`

Get the status of an asynchronous business operation by operationId (returned by capabilities such as sites.create mode=brief or imports.create, or carried on webhook events). Poll until status is terminal (SUCCEEDED, FAILED, CANCELLED, EXPIRED); respect pollAfterSeconds. UNKNOWN means an external call timed out and Kanorio is reconciling it: keep polling, do not retry the original request. pendingEffects lists side effects still in flight after the main operation succeeded. Synchronous operations never create an operation; retry them with the same Idempotency-Key instead. import_job operations stay RUNNING with stage=review while the batch waits for a human (or imports.apply) to confirm which rows to write; result carries batchId, batchStatus and totals. Errors: OPERATION_NOT_FOUND, FORBIDDEN.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | — |

**Response** (200)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `operationId` | string | yes | — |
| `kind` | "site_job" \| "page_job" \| "outbox" \| "external" \| "import_job" \| "automation_run" | yes | — |
| `status` | "PENDING" \| "RUNNING" \| "SUCCEEDED" \| "FAILED" \| "CANCELLED" \| "UNKNOWN" \| "EXPIRED" | yes | PENDING / RUNNING / SUCCEEDED / FAILED / CANCELLED; UNKNOWN = an external call timed out and is being reconciled (not a failure); EXPIRED = the record passed its retention window. |
| `stage` | string \| null | yes | — |
| `websiteId` | string \| null | yes | — |
| `result` | object \| null | yes | — |
| `error` | object \| null | yes | — |
| `error.code` | string | yes | — |
| `error.message` | string \| null | yes | — |
| `pendingEffects` | object[] | yes | — |
| `pendingEffects[].kind` | string | yes | Side effect still being processed after the main operation succeeded (e.g. entitlement_grant, invoice_issue, webhook_delivery). |
| `pendingEffects[].status` | "PENDING" \| "RUNNING" \| "SUCCEEDED" \| "FAILED" \| "CANCELLED" \| "UNKNOWN" \| "EXPIRED" | yes | — |
| `pollAfterSeconds` | integer \| null | yes | Suggested wait before polling again; null when terminal. |
| `createdAt` | string | yes | — |
| `finishedAt` | string \| null | yes | — |

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `OPERATION_NOT_FOUND` | 404 | — |
| `FORBIDDEN` | 403 | — |

```bash
curl -X GET "https://app.kanorio.com/api/v1/operations/{id}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
```

```json
{
  "operationId": "op_site_job_job_example01",
  "kind": "site_job",
  "status": "RUNNING",
  "stage": "generating_pages",
  "websiteId": "ws_example123",
  "result": null,
  "error": null,
  "pendingEffects": [],
  "pollAfterSeconds": 8,
  "createdAt": "2026-10-01T02:30:00.000Z",
  "finishedAt": null
}
```
