Skip to content
.seventhings.com

Prefill your credentials

Fill in your non-secret values to have them appear in the examples below. Stored locally in your browser.

TypeScript SDK

The TypeScript SDK wraps the customer API and has no runtime dependencies. It uses the standard fetch API, so it runs on Node.js, Bun, Deno, browsers and edge runtimes. Resources are grouped into services on the client, for example client.objects. See the SDKs overview for the concepts all SDKs share, and common workflows for side-by-side examples.

Terminal window
npm install @seventhingscompany/customer-api

Pass your instance URL. The SDK appends /customer-api/v1 itself.

To log in while creating the client, use credentials:

import { SeventhingsClient } from '@seventhingscompany/customer-api';
const client = await SeventhingsClient.withCredentials({
instanceUrl: 'https://your-instance.seventhings.com',
username: 'user@example.com',
password: 'password',
clientId: 'your-client-id',
});

If another part of your application already completed the auth flow, pass the existing token:

const client = new SeventhingsClient({
instanceUrl: 'https://your-instance.seventhings.com',
token: 'access-token',
clientId: 'your-client-id',
});

To log in manually, construct the client first. The constructor also accepts a default timeout, extra headers and a custom fetch:

const client = new SeventhingsClient({
instanceUrl: 'https://your-instance.seventhings.com',
timeoutMs: 30_000,
headers: { 'User-Agent': 'my-app/1.0' },
});
const tok = await client.auth.login('user@example.com', 'password', 'your-client-id');
// login stores tok.accessToken on the client.

The other auth methods are:

  • client.auth.refresh(refreshToken)
  • client.auth.loginSSO(provider, authCode, clientId, appTarget)
  • client.auth.revokeTokens()

client.token and client.setToken(token) read and replace the current bearer token. client.clientId returns the stored OAuth client ID.

Each resource group is a property of the client: auth, objects, rooms, locations, persons, users, tasks, rentals, fieldDefinitions, files, reports and circularityHub. Every method returns a Promise.

const objects = await client.objects.list();
const uuid = await client.objects.create({ inventory_name: 'MacBook Pro 16' });
const object = await client.objects.get(uuid);
await client.objects.patch(uuid, { inventory_name: 'MacBook Pro 16 M4' });
await client.objects.delete(uuid);

Objects, rooms, locations and CircularityHub items have field keys configured per instance, so they are returned as Record<string, unknown>. Wrap a record in Fields to read values with the right type:

import { Fields } from '@seventhingscompany/customer-api';
const obj = new Fields(await client.objects.get(uuid));
obj.string('inventory_name'); // string | undefined
obj.time('purchase_date'); // Date | undefined

The SDK types the common person columns (person.firstName, person.email, and so on). It also keeps the complete field map, including custom fields, in person.fields.

Tasks, rental cases, users, files, field definitions and CircularityHub orders are typed with camelCase properties. The SDK converts them to and from the API’s snake_case field names.

Objects, rooms, locations, rental cases and CircularityHub lists take ListOptions:

import { Filter, SortDirection } from '@seventhingscompany/customer-api';
const objects = await client.objects.list({
page: 1,
perPage: 50,
sort: { updated_at: SortDirection.Desc },
filters: [Filter.like('inventory_name', 'Laptop'), Filter.in('status', 'active', 'pending')],
});

Users and persons take sortBy and order:

const users = await client.users.list({ perPage: 50, sortBy: 'email', order: 'asc' });
const persons = await client.persons.list({ perPage: 50, sortBy: 'last_name', order: 'asc' });

Tasks take filters (status, deadlineFrom, deadlineTo, assignee, author, referenceType). They don’t use the shared page/per-page model: the API returns up to 10,000 matching tasks.

all() returns an async iterator that fetches every page for you:

for await (const object of client.objects.all({ perPage: 100 })) {
console.log(object.uuid, object.string('inventory_name'));
}

all() exists on objects, rooms, locations, persons, users and rentals. On CircularityHub it is called allItems().

  • It ignores page, because the iterator controls paging.
  • perPage sets the page size and defaults to 100.
  • A break stops further requests.
const defs = await client.fieldDefinitions.list('asset'); // 'asset' | 'room' | 'person'
const missing = await client.fieldDefinitions.missingMandatoryFields('asset', {
inventory_name: 'MacBook Pro 16',
});
if (missing.length > 0) {
// prompt for the missing field keys before calling objects.create
}

These checks skip system-managed keys, because the server fills them in.

A response with status code 400 or higher rejects with an ApiError:

import { ApiError, isFeatureInactive, isNotFound } from '@seventhingscompany/customer-api';
try {
await client.objects.get(uuid);
} catch (err) {
if (isNotFound(err)) {
// handle a missing object
} else if (err instanceof ApiError && err.isUnauthorized()) {
// refresh the token, then retry
}
throw err;
}

isFeatureInactive(err) returns true when a module such as rentals is not enabled on the instance.

For other failures:

  • A request that gets no response (DNS, connection or TLS failure) rejects with NetworkError. The original error is in err.cause.
  • Aborts and timeouts reject with the runtime’s native AbortError or TimeoutError.

Every method accepts an optional final options argument:

const controller = new AbortController();
await client.objects.list(undefined, { signal: controller.signal });
await client.reports.create(input, { timeoutMs: 120_000 });