# Projects

> A project is the saved unit of work in Kaitoi. It holds a graph, carries a version for safe concurrent edits, and is the thing the REST API reads and writes.

Source: https://kaitoi.io/docs/concepts/projects/
Section: Concepts
Written for: Anyone building on Kaitoi, whether through the app or the REST API.
Last reviewed: 2026-09-16

---

A project is the saved unit of work in Kaitoi. Open Kaitoi Studio and the thing
on your canvas is a project. Call the REST API and the thing you create, list,
read and update is the same project. There is no separate developer-side object
that shadows it.

Each project holds one graph, some display metadata, and a version number. That
is close to the whole model.

## What a project carries

| Field | What it is |
|---|---|
| `id` | Stable identifier. Use it for every subsequent call. |
| `name` | Display name, shown in Kaitoi Studio. |
| `nodeCount` | How many nodes are in the project graph. |
| `version` | Optimistic concurrency version. See below. |
| `createdAt`, `updatedAt` | Timestamps, when available. |
| `thumbnailUrl` | Short-lived signed preview URL, when a thumbnail exists. |

The thumbnail URL expires. `thumbnailExpiresAt` tells you when. Store the
project id and re-read the project when you need a fresh URL, rather than
caching the URL itself.

## Version is a concurrency check, not a history

Every project carries a `version`. Write endpoints require you to send the
version you last read. If someone else has saved in the meantime, the server has
moved on and your write is rejected rather than applied on top of work you never
saw.

The correct response to that rejection is to re-read the project, reconcile, and
retry. It is not an error in the sense of something being broken. It is the
system refusing to silently discard an edit.

This matters more than it sounds, because a project can be open in Kaitoi Studio
and driven by your code at the same time.

## Two shapes of the same graph

A project's graph is readable in two different shapes, and picking the wrong one
costs you an afternoon.

**The project document**, at `/projects/{id}/document`, is the editable shape. It
uses input maps and `from`/`to` connection tuples, and it is designed for round
trips: read it, change it, write it back. If you are generating or modifying
projects programmatically, this is the one you want.

**The project graph**, at `/projects/{id}/graph`, is a read-only sanitized
snapshot for inspection. Internal metadata, execution history and private
storage paths are deliberately left out. It answers "what is in here" rather
than "let me change this".

Writing back is available as a full replace (`PUT /document`) or as ordered
semantic operations applied atomically (`PATCH /document`). Both validate the
result and both save through the same path, so a project written by the API is
an ordinary project that opens in Kaitoi Studio.

## Your own identifiers

If you are building a product on Kaitoi and your users never see Kaitoi itself,
you will want to map projects back to your own records. Three optional fields
exist for that:

- `externalId`, your identifier for the project
- `externalUserId`, your identifier for the end user it belongs to
- `externalWorkspaceId`, your identifier for their team or workspace

These are yours to define. Kaitoi stores them, returns them, and lets you filter
on them. `externalUserId` additionally acts as a guard on runs: a run declaring
an `externalUserId` will only accept file inputs belonging to that same user, so
one of your customers cannot reference another's uploads.

## Current limitations

- Project deletion is blocked while an active project still references a file
  you are trying to remove. The check fails closed.
- Listing is ordered by most recently updated first, and paginated with opaque
  cursors. Do not parse or construct a cursor. It is not a stable offset and the
  format is free to change.
