Protocol / SDK / Data APIs
shippedLayer 1 · Protocol

Data APIs

The client surface for reading and writing a space's data across the KV, SQL, and DuckDB services, each call an authorized invocation.

Data APIs

The data APIs are the client methods for reading and writing a space's data through the KV, SQL, and DuckDB services. Every call is an authorized invocation under the hood — the SDK signs it with the session key and the node verifies the capability chain (cacao-chain-validation).

Shape

  • KV (KVService): get / put / batchPut / list / delete / head / createSignedReadUrl / withPrefixtinycloud.kv/*.
  • SQL/DuckDB (SQLService/DuckDbService): db().query / execute / batch / executeStatement / exporttinycloud.sql/* / tinycloud.duckdb/*.
  • Per-space helpers: kvForSpace(spaceId), sqlForSpace(spaceId) target a space other than the default.
  • All methods are Result-typed (explicit ok/err rather than throwing).

Mechanics

Each method builds the capability invocation (resource {spaceId}/{service}[/path] + ability) and sends it with the session UCAN; the node authorizes and dispatches to the service. Authority must already exist — these APIs use capabilities granted at sign-in or via the delegation-api.

Example

From the browser, a signed-in TinyCloudWeb reads and writes the owner's KV directly. Every call returns a Result:

import type { TinyCloudWeb } from "@tinycloud/web-sdk";

async function saveNote(tcw: TinyCloudWeb, id: string, body: string) {
  const put = await tcw.kv.put(`notes/${id}`, body);
  if (!put.ok) throw new Error(put.error.message);

  const got = await tcw.kv.get(`notes/${id}`);
  if (!got.ok) throw new Error(got.error.message);
  return got.data.data; // the stored value
}

On a backend, a delegated DelegatedAccess (from node.useDelegation(...)) exposes the same surface, and access.sql.db(name) targets a named SQLite database (the bare access.sql shortcut uses the db named default):

import type { DelegatedAccess } from "@tinycloud/node-sdk";

async function listNotes(access: DelegatedAccess) {
  const sql = access.sql.db("main");
  const res = await sql.query(
    "SELECT id, title FROM notes ORDER BY updated_at DESC",
    [],
  );
  if (!res.ok) throw new Error(res.error.message);
  return res.data.rows; // rows aligned to res.data.columns
}

Schema setup uses the migration primitive rather than cold DDL in a hot path — sql.db("main").migrations.apply({ namespace, migrations: [{ id, sql: [...] }] }) — and the SQL resource must request the tinycloud.sql/schema action (see tinycloud-app-kit).

Relationships

Client surface over kv / sql / duckdb; each call an invocation of a capability; scoped to an space; authority comes from sign-in-flow / delegation-api; used along the getting-started path; also reachable from the cli.

Status & drift

Shipped. Result-typed surface; per-space helpers (kvForSpace/sqlForSpace) are recent additions.

Sources

  • js-sdk: packages/sdk-services/src/{kv/KVService.ts, sql/SQLService.ts, duckdb/DuckDbService.ts}