Client SDKs
HVAKR provides official client SDKs that wrap the v0 REST API so you don’t have to construct requests by hand.
Available SDKs
Section titled “Available SDKs”TypeScript / JavaScript
Section titled “TypeScript / JavaScript”For Node.js and browser applications.
npm install @hvakr/clientRepository: https://github.com/flowcircuits/hvakr-client
Python
Section titled “Python”For Python applications and scripts.
pip install hvakrRepository: https://github.com/flowcircuits/hvakr-python
TypeScript SDK
Section titled “TypeScript SDK”Basic usage
Section titled “Basic usage”The client is constructed with an access token (created in Settings → Developer). All methods live directly on the client instance.
import { HVAKRClient } from '@hvakr/client'
const client = new HVAKRClient({ accessToken: process.env.HVAKR_ACCESS_TOKEN! })
// List the projects you can accessconst { projects } = await client.listProjects()
// Fetch a single project (pass true to include all subcollections)const project = await client.getProject('project-id')const fullProject = await client.getProject('project-id', true)
// Run the calculator (one run; select sections with `include`)const { loads } = await client.getProjectCalculations('project-id', { include: ['loads'],})Methods
Section titled “Methods”Account
me()— the authenticated caller: identity, organization memberships, plan, and per-minute rate-limit budget. A good first call to confirm the token and see what it can do.
Projects
listProjects({ limit?, cursor?, search?, status?, projectType? })— paginated project summaries; page withnextCursorwhilehasMoreis true.searchfilters case-insensitively over name/number/address;statusandprojectTypeare exact filtersgetProject(id)/getProject(id, expand)— fetch a project;expandistrue(all subcollections), or an array like['spaces','zones','exports']. Expandedexportscome back in the public export shape (id, status,downloadUrlwhen completed)createProject(data, opts?)— create a project from anExpandedProjectPostupdateProject(id, data, opts?)— partial update; subcollections are deep-merged and anullvalue deletes a fielddeleteProject(id)— soft-delete (requires the Admin or Owner role)
createProject, updateProject, createJob, and createSheetFile accept opts.idempotencyKey, sent as the Idempotency-Key header. The API only enforces it on the create methods, so those are the ones safe to retry — a repeated request with the same key replays the original response instead of repeating the action. updateProject’s key is accepted and sent but not yet enforced by the API, so retries there aren’t deduplicated. deleteProject has no opts parameter.
Calculations
getProjectCalculations(id, { include? })— run the calculator once and return the requested sections.includeis any ofloads,register_schedule,graph,ventilation,equipment,checksums,airflows; omit it for every section (the response can be large). Each requested section appears as a field on the result alongsideerrorsandflags.
Jobs
createJob(id, body, opts?)— create a job.body.typeisauto-group,check,export,auto-takeoff, orauto-route. Export jobs also requirebody.definition(load-calculation,basis-of-design,ventilation-csv, orhourly-loads-csv).auto-group/checkrun synchronously and returnstatus: "completed"with aresult;export/auto-takeoff/auto-routereturnstatus: "queued".createSheetFile(id, { file, fileName, name? }, opts?)— upload one PDF (maximum 30 MiB) and receive asheet-uploadjob. The upload filename remains the source identity;nameis display-only.getJob(id, jobId)— poll a job;export/auto-takeoff/auto-route/sheet-uploadjobs settle fromqueued/runningtocompleted/failed. A completed sheet-upload job contains pages andreadyForTakeoff; patchsheetsif placement is needed, then run project-wide auto-takeoff.
Products
searchProducts({ search?, type?, limit?, cursor? })— search accessible catalog products (organization + public). Returns slim cards (id,name,manufacturer,model,type), paginated likelistProjects(defaultlimit20, max 100; page withnextCursorwhilehasMore). Optional case-insensitivesearchover name/manufacturer/model; optional exacttype(e.g.AIR_CLEANER) can be used alone to browse.getProduct(id)— a single catalog product (full specs)
Webhooks
Section titled “Webhooks”The SDK ships a helper to verify and parse webhook payloads:
import { constructWebhookEvent } from '@hvakr/client'
const event = constructWebhookEvent({ payload: rawRequestBody, signature: req.headers['x-hvakr-signature'] as string, secret: process.env.HVAKR_WEBHOOK_SECRET!,})Error handling
Section titled “Error handling”Failed requests throw an HVAKRClientError:
import { HVAKRClient, HVAKRClientError } from '@hvakr/client'
try { const project = await client.getProject('id')} catch (error) { if (error instanceof HVAKRClientError) { // error.message describes the API response }}Python SDK
Section titled “Python SDK”The Python client mirrors the same set of operations as the TypeScript client (in snake_case). See the repository for exact signatures.
import osfrom hvakr import HVAKRClient
client = HVAKRClient(access_token=os.environ['HVAKR_ACCESS_TOKEN'])
projects = client.list_projects()project = client.get_project('project-id')calculations = client.get_project_calculations('project-id', include=['loads'])- The SDK request/response types are the same
*_v0Zod schemas the API validates against, so the TypeScript client cannot drift from server-side validation. - For the authoritative request/response shapes, see the live OpenAPI reference at https://api.hvakr.com/v0/docs/.