Workspaces

Domains

client.domains manages the domains a workspace classifies its files against. See Domains for the concept, and the API reference for every field.

  • A domain is a two-level taxonomy: a list of classes, each a group and a subgroup with a description written for the classifier.
  • Whose it is: Nace provides some (owner: "platform"), and your account can author its own (owner: "tenant").
  • Cost: managing domains costs nothing and works at any balance.

A domain version is a draft or published:

StateWhat you can do
DraftEdit it in place, as often as you like, then publish it once. Publishing is one-way.
PublishedGive it to a new workspace. It never changes again: duplicate it and edit the copy.

Nace's own domains never change either: copy them the same way. A workspace is pinned to the version it was made with, so editing a copy never reaches it.

Every method that works on one domain takes its domainId first; one you can't see rejects with NotFoundError, code domain_not_found.

  • A taxonomy is a list of classes, { classes: [...], allow_other: true }. A document that fits no class is labelled as such, not forced into one. Each class has:

    • group and subgroup: lowercase letters, digits and single underscores, up to 64 characters each.
    • description: what the classifier reads.
    • aliases (optional): earlier names.

    If a class doesn't follow these rules, the whole create or update is refused with 422 invalid_request, and nothing is saved.

  • A write returns its validation: create, update, publish and duplicate return a DomainWrite, with the saved domain and a validation of what is wrong with the taxonomy so far. A draft that follows the rules can still be one publish refuses, with domain_validation_failed: one with no classes, or with a class in the reserved group other.

  • Errors: a published domain passed to update or publish rejects with ConflictError (domain_not_editable), and a platform one with PermissionDeniedError. A taxonomy that fails validation on publish rejects with UnprocessableEntityError (domain_validation_failed), with the rules to fix in detail. A limit outside 1 to 200, or a domainId that is empty or holds /, ? or #, throws a NaceError before any request.

  • No automatic retries on creates: create, publish and duplicate aren't idempotent, since a retry after the first call landed answers 409 or makes a second copy. They aren't retried unless you pass retry in options. list, iter, get and update are retried.

List domains

client.domains.list(params?, options?) returns APIPromise<DomainPage>, one page of the domains your account sees, the platform's and its own. params is a DomainListParams.

ParameterTypeRequiredDescription
owner"platform" | "tenant"NoOnly the platform's domains, or only your account's.
status"draft" | "published"NoOnly drafts, or only published versions. Only a published one can create a workspace.
slugstringNoOnly the versions of this slug.
limitnumberNo1 to 200. Default: 50.
cursorstring | nullNoThe previous page's next_cursor. Keep going until it's null.
list-domains.ts
const page = await client.domains.list({ owner: "platform", status: "published" });
for (const domain of page.items) {
  console.log(domain.slug, domain.version, domain.class_count);
}

Iterate over domains

client.domains.iter(params?, options?) returns AsyncGenerator<DomainSummary>, following every page, 200 a page.

ParameterTypeRequiredDescription
owner"platform" | "tenant"NoOnly the platform's domains, or only your account's.
status"draft" | "published"NoOnly drafts, or only published versions.
slugstringNoOnly the versions of this slug.
iter-domains.ts
for await (const domain of client.domains.iter({ owner: "tenant" })) {
  console.log(domain.domain_id, domain.slug, domain.status);
}

Create a domain

client.domains.create(params, options?) returns APIPromise<DomainWrite>: a draft owned by your account. params is a CreateDomainParams.

ParameterTypeRequiredDescription
slugstringYesLowercase letters, digits and single underscores, up to 64. It can't change later. A slug in use throws ConflictError.
display_namestringYes1 to 200 characters.
taxonomyRecord<string, unknown>NoThe classes, as described above. Default: empty.
create-domain.ts
const draft = await client.domains.create({ slug: "leases", display_name: "Leases" });
console.log(draft.domain.domain_id, draft.validation.valid);

Read a domain

client.domains.get(domainId, options?) returns APIPromise<Domain>: one domain version with its taxonomy.

ParameterTypeRequiredDescription
domainIdstringYesThe domain version.
get-domain.ts
const domain = await client.domains.get(domainId);
console.log(domain.taxonomy, domain.published_at);

Update a draft

client.domains.update(domainId, params, options?) returns APIPromise<DomainWrite>, as saved. params is an UpdateDomainParams; a field you leave out stays as it is.

ParameterTypeRequiredDescription
domainIdstringYesThe draft.
params.display_namestringNoThe new name, 1 to 200 characters.
params.taxonomyRecord<string, unknown>NoReplaces the whole taxonomy.
update-domain.ts
await client.domains.update(draft.domain.domain_id, {
  taxonomy: {
    classes: [
      { group: "leases", subgroup: "amendments", description: "Amendments to a signed lease.", aliases: [] },
    ],
  },
});

Publish a domain

client.domains.publish(domainId, options?) returns APIPromise<DomainWrite>: the draft, frozen, so workspaces can use it by its slug. It is one-way.

ParameterTypeRequiredDescription
domainIdstringYesThe draft.
publish-domain.ts
const published = await client.domains.publish(draft.domain.domain_id);
console.log(published.domain.selectable, published.validation.valid);

Duplicate a domain

client.domains.duplicate(domainId, options?) returns APIPromise<DomainWrite>: a draft copy of any domain you see, the platform's included, under a new slug. Workspaces pinned to the original never see the copy.

ParameterTypeRequiredDescription
domainIdstringYesThe domain to copy.
duplicate-domain.ts
const copy = await client.domains.duplicate(published.domain.domain_id);
console.log(copy.domain.slug, copy.domain.status); // a draft under a new slug

Create a workspace against a domain

Pass the published domain's slug as domain_slug. See Create a workspace.

workspace-with-domain.ts
const workspace = await client.workspaces.create({ name: "fy25-leases", domain_slug: "leases" });
console.log(workspace.domain_slug, workspace.domain_id);

On this page