Docs

Reading & Writing

Create, read, and list objects through the typed API. Reach for this whenever you need to write a record, fetch one by id, or page through a type's objects in code.

Once an object type is registered, sixb.objects(Type) returns a typed collection ("object set"). TypeScript infers property names and value types from your ontology, so writes and reads are checked as you type.

TS
import { Invoice } from "./ontology/invoice"

const invoices = sixb.objects(Invoice)

The methods below live on that object set. For filtering, search, and link traversal see Querying. For time-series values see Telemetry.

upsert

upsert creates an object if it does not exist, or updates it if it does. It is keyed by the primary property declared on the object type.

The primary id goes inside properties — there is no separate key field. Upsert throws if it is missing.

TS
const invoice = await invoices.upsert({
  properties: {
    id: "inv-001",
    number: "INV-2026-001",
    amount: 4800,
    currency: "EUR",
    status: "sent",
    dueDate: "2026-07-15",
  },
})

The return value is the stored object, including createdAt and updatedAt as Date values.

Merge semantics

Upsert merges into the existing record. Only the properties you pass are written; omitted properties keep their current values, so you can update one field without re-sending the whole object.

TS
// Creates the invoice
await invoices.upsert({ properties: { id: "inv-001", number: "INV-2026-001", amount: 4800 } })

// Updates only `status`; `number` and `amount` are preserved
await invoices.upsert({ properties: { id: "inv-001", status: "paid" } })

Required properties are checked against the merged result, not just the incoming fields, so a later partial update of an existing object need not repeat required values.

Dates are normalized

The typed surface accepts Date | string for date and timestamp properties. Before storage, Date values are normalized to ISO strings. Both forms below are equivalent:

TS
await invoices.upsert({ properties: { id: "inv-001", issuedAt: new Date() } })
await invoices.upsert({ properties: { id: "inv-001", issuedAt: "2026-06-23T00:00:00.000Z" } })

Events

Each successful upsert appends an object.upserted event carrying the object type id, primary id, and the properties you wrote. The object record is projected from that event, and rules and workflows can react to it.

get

get(id) reads a single object by its primary id. It returns the object, or null if none exists.

TS
const invoice = await invoices.get("inv-001")

if (invoice) {
  console.log(invoice.properties.amount, invoice.properties.status)
  console.log(invoice.createdAt, invoice.updatedAt)
}

The returned object has this shape:

FieldTypeMeaning
primaryIdstringThe object's primary id
objectTypeIdstringThe object type id, like "Invoice"
propertiestypedProperty values inferred from the ontology
createdAtDateWhen the object was first written
updatedAtDateWhen the object was last written

You can also read through a handle: invoices.byId("inv-001").get().

list

list(...) browses stored objects of this type directly from storage — a fast, index-friendly scan by primary id and timestamps. Use it to page through objects or fetch a window of recent records. For property predicates, full-text search, or link traversal, use query() instead.

TS
const { objects, hasMore, total } = await invoices.list({
  limit: 200,
  orderBy: "updatedAt",
  order: "desc",
})

All options are optional:

OptionTypeMeaning
idPrefixstringOnly ids starting with this prefix
idSuffixstringOnly ids ending with this suffix
createdAfterDateCreated strictly after this time
createdBeforeDateCreated strictly before this time
updatedAfterDateUpdated strictly after this time
updatedBeforeDateUpdated strictly before this time
limitnumberMaximum objects to return
offsetnumberObjects to skip, for paging
orderBy"createdAt" | "updatedAt" | "primaryId"Sort key
order"asc" | "desc"Sort direction

The result is { objects, hasMore, total }: the matching objects, a hasMore flag, and the total count matching the filters. Page through with offset and limit:

TS
const page1 = await invoices.list({ limit: 50, offset: 0, orderBy: "primaryId" })
const page2 = await invoices.list({ limit: 50, offset: 50, orderBy: "primaryId" })

list vs query

UseReach for
Browse by id prefix/suffix, created/updated time, or page raw recordslist(...)
Filter by property values, search text, traverse links, aggregatequery()
TS
// Storage browse: recent records, no property filter
const recent = await invoices.list({ orderBy: "updatedAt", order: "desc", limit: 20 })

// Query: filter by a property value (status is filterable in the ontology)
const overdue = await invoices
  .query()
  .where((i) => i.p.status.eq("overdue"))
  .limit(10)
  .list()

Only properties that declare query metadata can be filtered or sorted. See Querying for the full builder.

The byId handle

byId(id) returns a handle bound to one object id. It is the entry point for per-object operations: reading, links, telemetry, and actions.

TS
const handle = invoices.byId("inv-001")

await handle.get()

// Link to a customer (link tokens live on Type.l.*, targets are object refs)
await handle.link(Invoice.l.customer, { objectTypeId: "Customer", primaryId: "cust-001" })

await handle.requestAction({ actionId: "markPaid" })

The handle does not check that the object exists when you create it; operations are validated when they run.

requestAction

requestAction requests an action against an object. It enqueues the request and returns immediately; a handler runs the action asynchronously.

On a byId handle, pass the action id (or an imported action definition) and any params:

TS
await invoices.byId("inv-001").requestAction({
  actionId: "markPaid",
  params: { paymentMethod: "wire", paymentReference: "txn-9921" },
})

On the object set, also pass the target id:

TS
await invoices.requestAction({
  id: "inv-001",
  actionId: "sendReminder",
})

Both forms accept either actionId (a string) or action (an imported action definition). Use requestActionAndWait(...) to block until the action completes. See Actions for handlers, params, and results.

appendTelemetryBatch

appendTelemetryBatch appends telemetry values to many objects in one call. Each item names the target by primary id and the telemetry property values to append.

TS
await projects.appendTelemetryBatch([
  { id: "proj-001", properties: { progress: 40 } },
  { id: "proj-002", properties: { progress: 75 } },
])

For appending to a single object and reading history, see Telemetry.

  • Querying — filters, search, link traversal, aggregation
  • Telemetry — time-series property values
  • Actions — requesting commands against objects
  • HTTP reference — the same operations over HTTP

Search docs

Search the documentation