---
title: 'REST API: ScaiCore'
path: reference/rest-api/scaicore
status: published
---

# REST API: ScaiCore

Live event stream, checkpoint listing + resolution, and an invoke proxy. All proxied to ScaiGrid using the same auth precedence as the [lookups](./lookups).

## `GET /v1/scaicore/events`

Paginated event stream from `GET /v1/modules/scaicore/events` on ScaiGrid. Used by the canvas Live Runs panel.

**Query:**

- `core_id` — filter to one Core's events.
- `limit` — page size, default 50, max 500.
- `cursor` — opaque cursor for the next page.

**Response:**

```jsonc
{
  "data": {
    "events": [
      { "type": "scaicore.runtime.invocation.started",
        "core_id": "core_xxx",
        "timestamp": "2026-04-29T12:34:56Z",
        "payload": {
          "execution_id": "exec_xxx",
          "input": { "message": "hello" },
          "node_id": null
        } },
      { "type": "scaicore.runtime.block.entered",
        "core_id": "core_xxx",
        "timestamp": "2026-04-29T12:34:57Z",
        "payload": {
          "execution_id": "exec_xxx",
          "node_id": "node_classify",
          "block_kind": "flexible"
        } }
    ],
    "next_cursor": "..."
  }
}
```

Event payloads pass through verbatim — the proxy doesn't reshape them. New fields the runtime adds (e.g. `source_location.node_id` when populated) are forwarded as-is.

### Built-in runtime events (closed set)

ScaiCore auto-fires 6 events per invocation (no `@emit` needed):

- `scaicore.runtime.invocation.started` — carries `input`, optional `instance_key`.
- `scaicore.runtime.invocation.completed` — carries `output`, `duration_ms`, optional `instance_key`.
- `scaicore.runtime.invocation.failed` — carries error info.
- `scaicore.runtime.block.entered` — carries `block_kind` (one of 14 IR kinds), `node_id`.
- `scaicore.runtime.block.exited` — carries `result_binding`, `result_binding_value` (≤4 KB JSON; `result_binding_truncated: true` otherwise).
- `scaicore.runtime.block.failed` — carries error info, `block_kind`, `node_id`.

Flow authors can emit their own `@emit` events alongside these.

`scaicore:view`.

## `GET /v1/scaicore/checkpoints`

List ScaiCore checkpoints. Used by the canvas to surface paused executions (HITL Reviews + debug breakpoints).

**Query:**

- `core_id` — filter to one Core's checkpoints.
- `status` — defaults `pending`. Other values: `resolved`, `failed`.
- `limit` — page size, default 50, max 500.

**Response:**

```jsonc
{
  "data": {
    "checkpoints": [
      { "id": "ckpt_xxx",
        "core_id": "core_xxx",
        "checkpoint_type": "hitl_review",     // or "debug_breakpoint", "approval", ...
        "status": "pending",
        "presentation": { "title": "Review needed", "message": "..." },
        "options": ["approve", "reject"],
        "created_at": "2026-04-29..." }
    ],
    "next_cursor": "..."
  }
}
```

The `checkpoint_type` discriminator lets the canvas render different CTAs for `hitl_review` (form-based decision) vs. `debug_breakpoint` (just a Continue button).

`scaicore:view`.

## `POST /v1/scaicore/checkpoints/{checkpoint_id}/resolve`

Resolve a paused checkpoint. Resumes the suspended execution.

**Body:**

```jsonc
{
  "resolution": "approve",          // for HITL: one of the decision section's option ids
                                    // for debug_breakpoint: "continue"
  "comment": "Within budget."       // optional
}
```

**Response:** the resolved `Checkpoint`.

`scaicore:manage` (resuming has side effects — LLM calls, plugin calls, etc.).

## `POST /v1/scaicore/cores/{core_id}/invoke`

Invoke a deployed Core directly. Used by the canvas Live Runs panel's "↻ replay" button — extracts the captured input from an `invocation.started` event payload and fires it again.

**Body:**

```jsonc
{
  "input": { "message": "..." },
  "entity_id": "user_xxx"            // optional, for entity-mode Cores
}
```

**Response:** ScaiCore's `InvokeResponse`:

```jsonc
{
  "output": { /* flow-defined */ },
  "request_id": "req_xxx",
  "duration_ms": 412
}
```

`scaicore:manage` (invocations have side effects).

## Notes on the canvas integration

- The Live Runs panel polls `GET /v1/scaicore/events` every 5 s while open, using a monotonic `nextFetch` to drop out-of-order responses.
- Per-event `payload.node_id` (top-level) is what the canvas reads to correlate events back to canvas nodes. The runtime populates it from each block's `source_location.node_id` — which the compiler writes for every block we emit.
- The visual debugger overlay groups events by `execution_id` and computes per-node `NodeRunInfo` (entered → blue, exited → green, failed → red) from the event stream.
