Skip to content

REST and Storage

Both namespaces expose:

ts
request(path: string, init?: OpenCloudRequestInit): Promise<Response>

The client adds the app identity, current bearer token, same-origin cookies, and refresh behavior.

REST

Paths are relative to /rest/v1.

js
const response = await opencloud.rest.request(
  "items?select=id,title,created_at&order=created_at.desc",
);
if (!response.ok) throw new Error(await response.text());
const items = await response.json();

Insert and return rows:

js
const response = await opencloud.rest.request("items", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    prefer: "return=representation",
  },
  body: JSON.stringify({ title: "Review evidence" }),
});

Authenticated mode is the default. Use { auth: "anonymous" } only for a deliberately public RLS read. { auth: "optional" } uses the current user when present and the anonymous project identity otherwise.

Storage

Paths are relative to /storage/v1.

js
const config = await opencloud.config();
const session = await opencloud.session();
if (!session) throw new Error("Sign in required");

const objectName = [
  session.userId,
  crypto.randomUUID(),
  file.name.replaceAll("/", "_"),
].map(encodeURIComponent).join("/");

const response = await opencloud.storage.request(
  `object/${encodeURIComponent(config.storageBucket)}/${objectName}`,
  {
    method: "POST",
    headers: {
      "content-type": file.type || "application/octet-stream",
    },
    body: file,
  },
);

When the manifest uses owner-prefix, the first decoded object-name segment must exactly equal the current user ID. When it uses app, authenticated app users share the bucket namespace.

Never use artifact, deployment, or backup bucket names.

Self-hosted infrastructure for agent-built applications.