TypeScript SDK
Typed, zero dependencies, runs in Node 18+, Bun, Deno, edge runtimes and the browser.
npm i https://docs.roots.sh/dl/roots-sh-sdk-0.1.0.tgz
import { Roots } from '@roots-sh/sdk';
const roots = new Roots({ apiKey: process.env.ROOTS_API_KEY }); // reads ROOTS_API_KEY by default
const brief = await roots.farms.brief(); // your main farm when farmId is left out
for (const a of brief.alerts) console.log(a.severity, a.title, a.reason);
const cows = await roots.animals.list({ species: 'cattle', q: 'Angus' });
await roots.events.create({ type: 'weight', subject_type: 'animal', subject_id: cows.data[0].id, data: { kg: 548 } });
const [roost] = (await roots.roosts.list()).data;
await roots.roosts.command(roost.id, 'feed.dispense', { kg: 20 });
const temps = await roots.devices.readings(roost.id, { metric: 'climate.temp_c' });
Every list and create takes an optional farmId. Without it the SDK uses your first real farm, or the sample farm in test mode.
Resources
farms (list, get, create, update, delete, brief) · animals · groups · paddocks · devices (plus readings, commands, command, rotateKey) · roosts (list, get, command) · alerts (list, get, acknowledge, resolve) · tasks (plus done) · events · webhooks · keys · me · catalog · usage.
Errors throw RootsError with status, code and message.
Devices and gateways
import { RootsDevice } from '@roots-sh/sdk';
const device = new RootsDevice(process.env.ROOTS_DEVICE_KEY!);
const { commands } = await device.report({ readings: [{ metric: 'water.tank_pct', value: 72 }] });
for (const c of commands) await device.ack(c.id, 'done');
Webhooks
import { verifyWebhook } from '@roots-sh/sdk';
const ok = await verifyWebhook(secret, req.headers['roots-signature'], rawBody);