Skip to main content
Short, self-contained recipes using @gavai/sdk. Each example is a working snippet you can drop into a file and run with bun run. By the end of this page you will have seen every common pattern at least once — read calls, paginated lists, idempotent writes, rate-limit retries, and custom fetch injection.

Fetch the current user

me.ts
import { Gavai } from "@gavai/sdk";

const gv = new Gavai({ apiKey: process.env.GAVAI_API_KEY });

const me = await gv.me.get();
console.log(me.user_id, me.scopes);

Patch a page and publish

Fetch the current page, build an RFC 6902 JSON Patch operation array, apply it, then publish to live.
patch-page.ts
import { Gavai } from "@gavai/sdk";

const gv = new Gavai({ apiKey: process.env.GAVAI_API_KEY });

const workspace = "acme";
const pageId = "page_01H...";

// 1. Fetch the current page document
const page = await gv.pages.get({ workspace, id: pageId });

// 2. Build the patch — RFC 6902 operation array
const operations = [
  {
    op: "replace",
    path: "/blocks/0/props/title",
    value: "Updated hero title",
  },
];

// 3. Apply the patch
await gv.pages.patch({ workspace, id: pageId, operations });

// 4. Publish to live
await gv.pages.publish({ workspace });

Iterate a paginated list

Log resources use cursor-based pagination. Keep fetching until next_cursor is null.
paginate-logs.ts
import { Gavai } from "@gavai/sdk";

const gv = new Gavai({ apiKey: process.env.GAVAI_API_KEY });

const workspace = "acme";
let cursor: string | null = null;

do {
  const page = await gv.logs.list({
    workspace,
    ...(cursor ? { cursor } : {}),
  });

  for (const entry of page.items) {
    console.log(entry.timestamp, entry.message);
  }

  cursor = page.next_cursor;
} while (cursor);
See Pagination for query parameters and cursor semantics.

Make a write idempotent

Pass an idempotencyKey as the second-argument options object so retrying the same call after a network failure does not duplicate the operation.
idempotent-patch.ts
import { Gavai } from "@gavai/sdk";

const gv = new Gavai({ apiKey: process.env.GAVAI_API_KEY });

await gv.pages.patch(
  {
    workspace: "acme",
    id: "page_01H...",
    operations: [
      { op: "replace", path: "/blocks/0/props/title", value: "Safe retry" },
    ],
  },
  { idempotencyKey: "patch-page-01H-title-2026-05-11" },
);
See Idempotency for key format and caching window.

Handle a rate limit

Catch GavaiError with code === "rate_limited", wait for the duration the server signals via Retry-After, then retry once. Wrap in a bounded loop for production.
rate-limit.ts
import { Gavai, GavaiError } from "@gavai/sdk";

const gv = new Gavai({ apiKey: process.env.GAVAI_API_KEY });

async function fetchMeWithRetry() {
  try {
    return await gv.me.get();
  } catch (e) {
    if (e instanceof GavaiError && e.code === "rate_limited") {
      // Retry-After is in seconds; fall back to 5 s if absent
      const retryAfter = Number(e.headers["retry-after"] ?? 5);
      await Bun.sleep(retryAfter * 1000);
      return await gv.me.get();
    }
    throw e;
  }
}

Inject a custom fetch

Swap in a custom fetch implementation — useful for tests against a mock server or for environments that require proxy configuration.
custom-fetch.ts
import { Gavai } from "@gavai/sdk";

const customFetch: typeof fetch = async (input, init) => {
  console.log("outbound:", input);
  return fetch(input, init);
};

const gv = new Gavai({
  apiKey: process.env.GAVAI_API_KEY,
  fetch: customFetch,
});

const me = await gv.me.get();

Next steps