Overview
Getting started
Install the packages, wire up AssetProvider with an access token, and render your first card.
Install
Install the styled package — it re-exports everything from the SDK.
npm install @get-asset/react
If you only need headless components and intend to bring your own styles, install @get-asset/sdk directly.
npm install @get-asset/sdk
Set up the provider
AssetProvider takes the businessIdyou're displaying data for and an accessToken — either a string or an async function that returns one. Pass baseUrl only if you need to point at a non-default API (it defaults to https://api.getasset.com).
import { AssetProvider } from "@get-asset/react";import "@get-asset/react/theme.css";import "@get-asset/react/styles.css";export function Root({ children, businessId }) {return (<AssetProviderbusinessId={businessId}accessToken={() => fetchToken(businessId)}>{children}</AssetProvider>);}
Token exchange
Never ship client_id/client_secret to the browser. Exchange them for a short-lived access token on your server and proxy that to the client.
The token must carry the OAuth scopes that every card on the page needs. Import the per-card constants from @get-asset/sdk/scopes— this subpath has no React imports, so it's safe to use from Route Handlers, Server Components, or edge runtimes. Union the sets and pass the result as the standardscope form field. Each card's page (e.g. RevenueCard) lists its required scopes under Required scopes. Requesting a superset of what the dashboard needs is fine; missing a scope means the affected card will surface an error state at fetch time.
// app/api/token/route.ts//// Import scope constants from "@get-asset/sdk/scopes" — this subpath has no// React dependencies, so it's safe to use in Route Handlers, Server// Components, or edge runtimes.import {revenueCardScopes,expensesCardScopes,snapshotCardScopes,} from "@get-asset/sdk/scopes";// Union the scopes required by every card you intend to render.const SCOPES = [...revenueCardScopes,...expensesCardScopes,...snapshotCardScopes,];export async function GET(req: Request) {const { searchParams } = new URL(req.url);const businessId = searchParams.get("business_id");const res = await fetch(`${process.env.ASSET_API_URL}/v0/auth/token`, {method: "POST",headers: { "Content-Type": "application/x-www-form-urlencoded" },body: new URLSearchParams({client_id: process.env.ASSET_CLIENT_ID!,client_secret: process.env.ASSET_CLIENT_SECRET!,business_id: businessId ?? "",scope: [...new Set(SCOPES)].join(" "),}),});return Response.json(await res.json());}
Your first card
Every styled card is self-contained — drop it inside the provider and it'll fetch, show a skeleton while loading, surface an error state, and render the result.
import { AssetRevenueCard } from "@get-asset/react";export function Dashboard() {return <AssetRevenueCard year={2026} />;}
Shared period
AssetProvider also stores a year and an optional month (1-12). Year-aware cards default to these. Pass defaultYear / defaultMonth to set them on mount, or call setYear / setMonth from useAsset() to update them at runtime — every card re-fetches automatically.
With a month set, summary cards (Revenue, Expenses, Snapshot, OperatingExpenses) compare that month against the previous month. Without a month, they compare the full year against the previous year. ProfitLossCard always shows 12 months, so it ignores the provider's month.
import { AssetProvider, AssetRevenueCard, AssetSnapshotCard } from "@get-asset/react";// All cards default to 2026; SnapshotCard shows April 2026 vs March 2026.<AssetProviderbusinessId={businessId}accessToken={() => fetchToken(businessId)}defaultYear={2026}defaultMonth={4}><AssetRevenueCard /> {/* April 2026 vs March 2026 */}<AssetSnapshotCard /> {/* April 2026 vs March 2026 */}<AssetExpensesCard month={null} /> {/* whole 2026 vs 2025 — explicit override */}<AssetProfitLossCard /> {/* 12 months of 2026 — month ignored */}</AssetProvider>
To wire up a period picker that drives every card on the page, pull the setters from useAsset():
import { useAsset } from "@get-asset/sdk";function PeriodPicker() {const { year, month, setYear, setMonth } = useAsset();return (<><input type="number" value={year} onChange={(e) => setYear(+e.target.value)} /><select value={month ?? ""} onChange={(e) => setMonth(e.target.value ? +e.target.value : null)}><option value="">Whole year</option>{Array.from({ length: 12 }, (_, i) => (<option key={i + 1} value={i + 1}>{i + 1}</option>))}</select></>);}