# Work with projects and graph documents

> Discover node schemas, edit a versioned graph document through the public API, and reconcile changes without overwriting another client’s work.

Source: https://kaitoi.io/docs/core/projects-and-graphs/
Section: Kaitoi Core / REST API
Written for: Developers building or editing workflows through the public API.
Last reviewed: 2026-10-24

---

Use the public `/api/v1` project and graph-document endpoints for stable
integration contracts. Studio's internal persistence requests and public API
documents have different purposes; construct the shape described by the public
schema.

## Compare a focused edit with a whole graph


A focused patch changes the selected fields; replacing a graph supplies the complete intended graph. Capture the current project version, inspect the relevant nodes and preserve unrelated content. Version conflicts require rereading and comparing. An unresolved mutation or unavailable state must not become permission to resubmit automatically. The illustrated controls change only the example.

The A/B/C graph keeps its connections and other inputs. A narrow patch highlights only A’s strength change from 0.5 to 0.7; whole-document replacement highlights the enclosing document and its wider preservation responsibility.

*Figure: Review the part of the saved project that a write will replace.*

## Discover before building

Search node types and read the detail for each type you will place. Use the
actual input/output names, types, defaults, and requirements. A display label
such as “Reference image” is not automatically the pin identifier your graph
must use.

Assign stable instance IDs to placed nodes and use those IDs in connections and
run targets. A node type identifies an operation; a node instance identifies
that particular operation in your graph.

## Read, change, write

1. Fetch the current project or graph document and its version.
2. Make the intended change using the supported document or patch contract.
3. Send the observed version as `expectedVersion` where required.
4. Keep the version returned by a successful write for your next change.

If another client has already updated the document, read the new version and
reconcile your change. Blindly substituting the latest version number into an
old full document can still overwrite work you did not examine.

The version returned by a read is a conservative optimistic save base captured
before the content read. It is not a certificate of exact bytes during a
concurrent write. Guarded responses such as `PROJECT_MUTATION_UNRESOLVED` or
`PROJECT_SAVE_UNAVAILABLE` are not ordinary version conflicts. Preserve local
work and follow [the code-specific recovery path](/docs/core/errors-and-retries/#recover-a-guarded-project-save)
instead of automatically retrying.

## Keep graph state and executions separate

Saving graph changes does not execute them. A run snapshots a saved project or
accepts an inline graph. Non-persistent run input overrides change that execution
without rewriting the saved graph.

Use a saved project when users should reopen and edit the workflow. Use a
supported inline graph when the application needs a transient execution and
will manage its own source definition.

## Use current schemas

The [interactive API reference](https://api.studio.kaitoi.io/api/v1/docs) is the
field-level contract. Its generated schema also covers timeline and storyboard
documents. Use the corresponding document endpoints and validation rules for
those artifacts instead of treating rendered media as their editable source.

## Choose inspection, document replacement, or a narrow patch

**Inspect:** use the graph inspection response to understand state, and fetch
the editable document before writing. **Patch:** use a current expectedVersion
and narrow semantic operations for the intended pins or connections.
**Replace:** PUT the complete current document only after reconciling changes.
Changing a version number alone does not reconcile stale content. No project
is read, saved, deleted, or executed by these examples.

## Checks and next steps

`GET /projects/{id}/graph` is an inspection view, not the editable document.
Use `GET /projects/{id}/document` for the public editable shape; it requires
both `projects:read` and `graphs:read`. Nodes there use input maps and
connections such as `{"from":["a","image"],"to":["b","inputImage"]}`.

Replace through `PUT /projects/{id}/document` with `expectedVersion` and
`document`, or use `PATCH /projects/{id}/document` with `expectedVersion` and
1–100 semantic `operations`. Both writes require `projects:write` and
`graphs:write`. For a one-pin change, use `setNodeInput`/`unsetNodeInput`;
`updateNode.inputs` replaces the whole public input map. Read the current
schema for the exact operation fields.

Project metadata changes use `PATCH /projects/{id}/metadata` with the expected
version. Deletion also requires the current version. A failed or stale write
is a reason to inspect and reconcile state, not to copy a newer number into
an old replacement document. Run submission is separate and does not supply
the same expected-version guard for a saved-project run.
