Create one DataService with the tenant's API URL and a token getter, then call everything through it. Don't construct API classes from @cirrobio/api-client yourself.
import { DataService, FileService, ApiError } from "@cirrobio/sdk";
export const data = new DataService({
basePath: `${import.meta.env.VITE_CIRRO_URL}/api`, // see "Base path" below
tokenGetter: async () => (await userManager.getUser())!.access_token, // userManager: the template's oidc-client-ts UserManager
});
export const files = new FileService(data.file); // for file access; see "Working with files"
try {
const projects = await data.projects.getProjects();
const { data: datasets, nextToken } = await data.datasets.getDatasets({ projectId: projects[0].id, limit: 50 });
} catch (e) {
if (e instanceof ApiError) console.error(e.message, e.errors);
}The token getter runs before every request, so token renewal stays inside the sign-in library. Don't cache token strings yourself. The app template creates its DataService this way in src/main.tsx, with a token getter that also renews an expired token first (activeUser in src/auth.ts), and passes it to its components.
Use the tenant's web address followed by /api: https://<tenant>/api. It answers browsers from any origin (Access-Control-Allow-Origin: *, with Authorization allowed in preflights), so the app calls it directly from localhost and in production alike. https://api.<tenant>, which the Python client uses, returns the same data without CORS headers, so a browser can't read it. basePath defaults to /api, which only works on the Cirro origin itself, so always set it.
DataService has one getter per area of the API. The ones an app uses: projects, datasets, file, processes, execution, metadata, references, sharing, workspaces, sheets, feed (notes and discussions), dashboards, appRegistrations and system.
Every method takes a single object argument. Method and field names come from a generated client; look them up in the API reference and common models rather than guessing. The reference is a snapshot of 0.13.39; to regenerate it for the version you have installed:
python3 tools/api_surface.py node_modules > api-surface.mdList endpoints that page return { data, nextToken }. Pass nextToken back to get the next page, and stop when it's empty. In a UI, fetch pages on demand rather than everything up front.
The exception is a list the user searches or filters, which needs every item. getDatasets accepts limit: 1000; a project of 1,875 datasets comes back in two requests in under a second. A dataset's manifest pages differently: getDatasetManifest takes fileOffset and fileLimit and reports totalFiles, so ask again from the count received until it is reached.
The sdk turns any non-2xx response into an ApiError, with the server's message and a list of field errors. Show message to users and log errors.
errorCode is the HTTP status, so a refusal is e instanceof ApiError && e.errorCode === 403. Its message names the permission ("Not allowed to VIEW_PROJECT_METADATA on project …"), which is what to show the user.
- 401: no valid session. Check the sign-in.
- 403: the user or the registered app lacks a permission. Check the registration and the user's project role.
- Don't retry 4xx responses automatically.