Roots docs

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);