TypeScript SDK
Typed client over the Roboflare OpenAPI spec, runs in Node, Bun, and the browser.
The TypeScript SDK is a thin wrapper around openapi-fetch with the
generated types from packages/api-spec/openapi.json. Every method is
type-safe end to end.
Install
The SDK lives in this monorepo as packages/sdk-ts. Until it is
published to npm, link it locally:
pnpm add @roboflare/sdk@workspace:*Create a client
import { RoboflareClient } from "@roboflare/sdk";
const client = new RoboflareClient({
token: process.env.ROBOFLARE_TOKEN!,
baseUrl: "https://api.roboflare.com",
});token is a portal token (rf_org_... or rf_user_...). baseUrl
defaults to the hosted API.
Resources
The client exposes one object per resource:
await client.robots.list();
await client.robots.health(robotId);
await client.robots.timeline(robotId);
await client.robots.rosbags(robotId, { start_unix, end_unix });
await client.fleets.list();
await client.fleets.logs(fleetId);
await client.sites.list();
await client.sites.create({ name: "Warehouse A" });
await client.releases.list();
await client.releases.create({ semver: "1.2.3", notes: "..." });
await client.releases.deploy(releaseId, { fleet: fleetId });
await client.configs.list();
await client.configs.set({ name, namespace, payload });
await client.configs.deployments.list();
await client.configs.deployments.create({ config_blob_id, target_kind, target_id });
await client.configs.deployments.events(deploymentId);
await client.deployments.list();
await client.deployments.create({ release_id, target_kind, target_id });
await client.deployments.events(deploymentId);
await client.enrollmentKeys.list();
await client.enrollmentKeys.create({ site_id, fleet_id, name });
await client.enrollmentKeys.revoke(keyId);
await client.orgUsers.list();
await client.orgUsers.create({ email, role });
await client.orgUsers.revoke(userId);Idempotency
client.deployments.create() generates a UUIDv4 idempotency key for you
on every call. To make a retry safe, pass the same key:
const key = crypto.randomUUID();
await client.deployments.create({ release_id, target_kind: "robot", target_id }, key);
// safe to retry with the same key — returns the original deployment
await client.deployments.create({ release_id, target_kind: "robot", target_id }, key);Streaming logs
client.robots.logs(id) returns an async iterable backed by the live
WebSocket at /api/robots/<id>/logs/ws:
for await (const line of client.robots.logs(robotId)) {
console.log(line);
}Stop iterating to close the socket. The client appends ?token=... to
the WS URL automatically.
Errors
Failed calls throw RoboflareApiError with the raw payload attached:
import { RoboflareApiError } from "@roboflare/sdk";
try {
await client.deployments.create({ ... });
} catch (err) {
if (err instanceof RoboflareApiError) {
console.error("API rejected:", err.payload);
}
throw err;
}Bring-your-own login
For end-user portals where the user hasn't pasted a token yet, exchange
their portal token via client.login(portal_token) and store the
returned org/role pair. The HTTP client keeps using the bearer token you
passed at construction.