Examples

Worked SDK snippets — list projects, create monitors, fetch runs with citations, kick off prompt ingestion.

Every snippet here assumes you’ve already configured the SDK per the overview. All examples are TypeScript and run on Node 20+ and modern runtimes (Edge, Bun, Deno).

List all projects (paginated)

import { DefaultService } from "@citefoundry/api-client";
const projects: { id: string; name: string }[] = [];
let cursor: string | undefined;
do {
const page = await DefaultService.listProjects({ limit: 100, cursor });
projects.push(...page.items.map((p) => ({ id: p.id, name: p.name })));
cursor = page.nextCursor;
} while (cursor);
console.log(`Found ${projects.length} projects.`);

See Pagination for the cursor model.

Create a monitor

import { DefaultService } from "@citefoundry/api-client";
const monitor = await DefaultService.createMonitor({
projectId: "proj_01J...",
requestBody: {
promptId: "prom_01J...",
surface: "chatgpt", // see /v1/monitoring-surfaces for the catalog
cadence: "daily", // "daily" | "weekly"
},
});
console.log("Created", monitor.id);

The first run usually fires within a minute or two on Free and is near-instant on Pro/Business.

Fetch a run and iterate citations

import { DefaultService } from "@citefoundry/api-client";
const run = await DefaultService.getRun({ projectId, runId });
console.log(`Answer (${run.surface}, ${run.modelVersion}):`);
console.log(run.answer);
console.log("\nCitations:");
for (const c of run.citations) {
const owner = c.brand?.displayName ?? "(unknown)";
console.log(` [${owner}] ${c.url}`);
}
console.log("\nMentions:");
for (const m of run.mentions) {
console.log(` ${m.brand.displayName} (${m.surface})`);
}

Kick off prompt ingestion from CSV

import { DefaultService } from "@citefoundry/api-client";
import { readFile } from "node:fs/promises";
const csv = await readFile("./keywords.csv", "utf8");
const job = await DefaultService.startPromptSource({
projectId,
kind: "csv",
requestBody: { csv, defaultPersonaId: null },
});
console.log("Ingestion job started:", job.id);
// Poll until done — 5s intervals are fine for CSV-sized jobs.
while (true) {
const status = await DefaultService.getIngestionJob({ projectId, jobId: job.id });
if (status.state !== "pending" && status.state !== "running") break;
await new Promise((r) => setTimeout(r, 5000));
}
console.log("Done. Candidates ready for review in the dashboard.");

Pull GSC queries and start an ingestion

import { DefaultService } from "@citefoundry/api-client";
// Make sure the project has GSC connected first (use the dashboard
// for the OAuth dance).
const properties = await DefaultService.listGscProperties();
const property = properties[0];
const job = await DefaultService.startPromptSource({
projectId,
kind: "gsc",
requestBody: {
siteUrl: property.siteUrl,
country: "USA",
minImpressions: 100,
strict: true, // drop branded queries
},
});
console.log("GSC ingestion started:", job.id);

Get share-of-voice for a window

import { DefaultService } from "@citefoundry/api-client";
const sov = await DefaultService.getShareOfVoice({
projectId,
from: "2026-04-01",
to: "2026-04-30",
surface: "chatgpt",
});
for (const row of sov.brands) {
console.log(`${row.brand.displayName.padEnd(20)} ${row.share.toFixed(1)}%`);
}

Stream the runs of a monitor as JSON Lines

A small CLI utility — useful for piping into jq or a warehouse load.

import { DefaultService } from "@citefoundry/api-client";
const [, , projectId, monitorId] = process.argv;
let cursor: string | undefined;
do {
const page = await DefaultService.listRuns({
projectId,
monitorId,
limit: 100,
cursor,
});
for (const run of page.items) {
process.stdout.write(JSON.stringify(run) + "\n");
}
cursor = page.nextCursor;
} while (cursor);

What’s next

  • Error handling — wrap any of the above with retries, refresh, and graceful degradation.
  • API reference — schemas for every request and response shape used in these examples.