Skip to main content

TwinClient

Implements

Index

Constructors

constructor

  • new TwinClient(baseUrl: string | URL, _httpClient: TwinfinityHttpClient): TwinClient
  • Parameters

    • baseUrl: string | URL
    • _httpClient: TwinfinityHttpClient

    Returns TwinClient

Accessors

baseUrl

  • get baseUrl(): string
  • Rooted twins base URL — typically <host>/sites/<container>/_ps/twins. Exposed so callers that want to build content URLs in the same auth scope as the metadata calls can derive them from here. The bare <host>/_ps/twins/... variant is not necessarily an authorized route on all deployments.


    Returns string

Methods

batchAssets

  • Executes a batch of asset operations (upsert, delete, restore) atomically. All operations succeed or all are rolled back.

    @throws

    When the batch rolled back. The error's response has per-item results with reverted statuses, and is thrown for any status the failing item carried -- 400, 404 or 409.

    @throws

    When the whole request was rejected before any item ran (400): an empty batch, duplicate ids, a body/URL twin mismatch, oversized metadata.

    @throws

    On insufficient permissions (403).


    Parameters

    • twinId: string
    • operations: AssetBatchOperation[]

      Array of batch operations (max 1000).

    • optionalsignal: AbortSignal

    Returns Promise<AssetBatchResponse>

batchGetAssets

  • Retrieves multiple assets by ID in a single request.

    @throws

    On validation failure (400).


    Parameters

    • twinId: string
    • ids: string[]

      Array of asset IDs (max 1000).

    • optionalsignal: AbortSignal

    Returns Promise<AssetBatchGetResponse>

createAssetAttachmentUploadSession

  • Creates an upload session for a new attachment. The actual file bytes are uploaded out-of-band to ApiCreateUploadSessionResponse.uploadUrl; use uploadAssetAttachmentFile for the canonical chunked-upload flow. The attachment row is materialized server-side when the blob lands.

    @throws

    When an attachment already exists for the given id (409); retries must use a new attachmentId.


    Parameters

    • twinId: string
    • assetId: string
    • attachmentId: string
    • body: AttachmentPost
    • optionalsignal: AbortSignal

    Returns Promise<ApiCreateUploadSessionResponse>

createAssets

  • createAssets(twinId: string, assets: AssetPost[], signal?: AbortSignal): Promise<AssetGet[]>
  • @throws

    On invalid request body (400). The error's errorBody has structured detail.


    Parameters

    • twinId: string
    • assets: AssetPost[]
    • optionalsignal: AbortSignal

    Returns Promise<AssetGet[]>

createOrUpdateTwin

  • createOrUpdateTwin(twinId: string, twin: TwinPut, signal?: AbortSignal): Promise<TwinGet>
  • Creates a new twin or updates an existing one (upsert). Provide etag in the twin body to update.

    @throws

    On invalid request body (400).

    @throws

    On etag mismatch (409). The error's currentTwin contains the server's current state.


    Parameters

    • twinId: string
    • twin: TwinPut
    • optionalsignal: AbortSignal

    Returns Promise<TwinGet>

createOrUpdateTwinFile

  • createOrUpdateTwinFile(twinId: string, fileId: string, twinFile: TwinFilePut, signal?: AbortSignal): Promise<TwinFileGet>
  • @throws

    On invalid request body (400).

    @throws

    On etag mismatch (409). The error's currentTwinFile contains the server's current state.


    Parameters

    • twinId: string
    • fileId: string
    • twinFile: TwinFilePut
    • optionalsignal: AbortSignal

    Returns Promise<TwinFileGet>

createOrUpdateTwinFileRaw

  • createOrUpdateTwinFileRaw(twinId: string, fileId: string, twinFile: unknown, signal?: AbortSignal): Promise<Response>
  • Parameters

    • twinId: string
    • fileId: string
    • twinFile: unknown
    • optionalsignal: AbortSignal

    Returns Promise<Response>

createOrUpdateTwinRaw

  • createOrUpdateTwinRaw(twinId: string, twin: unknown, signal?: AbortSignal): Promise<Response>
  • Parameters

    • twinId: string
    • twin: unknown
    • optionalsignal: AbortSignal

    Returns Promise<Response>

deleteAsset

  • deleteAsset(twinId: string, assetId: string, etag: string, signal?: AbortSignal): Promise<AssetGet>
  • @throws

    When the asset does not exist (404).

    @throws

    On etag mismatch (409). The error's currentAsset contains the server's current state.


    Parameters

    • twinId: string
    • assetId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetGet>

deleteAssetAttachment

  • deleteAssetAttachment(twinId: string, assetId: string, attachmentId: string, etag: string, signal?: AbortSignal): Promise<AttachmentGet>
  • Soft-deletes an attachment.

    @throws

    On etag mismatch (409).

    @throws

    When the attachment does not exist (404).


    Parameters

    • twinId: string
    • assetId: string
    • attachmentId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<AttachmentGet>

deleteAssetCategory

  • deleteAssetCategory(categoryId: string, etag: string, signal?: AbortSignal): Promise<AssetCategoryGet>
  • Soft-deletes a category. Inserts a new asset_category_versions row with is_deleted=true; the previous version is retained as an audit trail.

    @throws

    When the category does not exist (404).

    @throws

    On etag mismatch (409).


    Parameters

    • categoryId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetCategoryGet>

deleteAssetPermissions

  • Removes the principal from the domain's access control list entirely, answering with it and an empty capability list.

    The answer carries the etag the revocation wrote: it belongs to the domain, not to the principal, so a revoked principal having no listing entry does not cost the caller one. Chain the next write on it exactly as with setAssetPermissions, without re-reading listAssetPermissions.

    The etag is always required — a revocation always replaces existing grants — and a request naming none is refused with a 400 rather than a conflict, before anything else is asked.

    @throws

    No group in the tenant carries this id, or it holds nothing here for a revocation to remove (404).

    @throws

    SystemPrincipalImmutable or EtagRequired (400).

    @throws

    EtagMismatch (409).

    @throws

    The caller does not hold ManageAssetPermissions (403).

    @throws

    No valid auth context (401).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • principalId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetPrincipalPermissionsGet>

deleteAssetType

  • deleteAssetType(categoryId: string, typeId: string, etag: string, signal?: AbortSignal): Promise<AssetTypeGet>
  • Soft-deletes a type. Inserts a new asset_type_versions row with is_deleted=true; the previous version is retained as an audit trail.

    @throws

    When the type does not exist (404).

    @throws

    On etag mismatch (409).


    Parameters

    • categoryId: string
    • typeId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetTypeGet>

deleteTwin

  • deleteTwin(twinId: string, etag: string, signal?: AbortSignal): Promise<TwinGet>
  • @throws

    When the twin does not exist (404).

    @throws

    On etag mismatch (409). The error's currentTwin contains the server's current state.


    Parameters

    • twinId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinGet>

deleteTwinFile

  • @throws

    When the file does not exist (404).

    @throws

    On etag mismatch (409). The error's currentTwinFile contains the server's current state.

    @throws

    On invalid request (400).


    Parameters

    • twinId: string
    • fileId: string
    • deleteRequest: TwinFileDelete
    • optionalsignal: AbortSignal

    Returns Promise<TwinFileGet>

deleteTwinPermissions

  • Removes the principal from the twin's access control list entirely — including any bits outside this capability vocabulary, which is what separates it from a setTwinPermissions call with an empty list.

    The etag is always required: a delete always replaces existing grants.

    @throws

    The principal holds nothing on the twin, so there is nothing to revoke and no entry to have read an etag from — whatever value was sent (404).

    @throws

    The principal is immutable through this surface (400), decided before the etag is looked at.

    @throws

    The twin does not exist or the caller cannot see it (404).

    @throws

    ManageTwinPermissions is required (403).

    @throws

    EtagMismatch or ScopesNotProvisioned (409).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • twinId: string
    • principalId: string
    • etag: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinPrincipalPermissionsGet>

downloadTwinContent

  • downloadTwinContent(twinId: string, twinVersion: number, content: TwinContentResponse, signal?: AbortSignal): Promise<ArrayBuffer>
  • Parameters

    Returns Promise<ArrayBuffer>

getAsset

  • getAsset(twinId: string, assetId: string, signal?: AbortSignal): Promise<AssetGet>
  • @throws

    When the asset does not exist (404).


    Parameters

    • twinId: string
    • assetId: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetGet>

getAssetAttachmentBlob

  • getAssetAttachmentBlob(twinId: string, assetId: string, attachmentId: string, signal?: AbortSignal): Promise<Response>
  • Downloads an attachment's blob as a Response. The caller decides whether to consume it as text, ArrayBuffer, or Blob.

    @throws

    When the attachment does not exist (404).


    Parameters

    • twinId: string
    • assetId: string
    • attachmentId: string
    • optionalsignal: AbortSignal

    Returns Promise<Response>

getAssetAttachmentUploadStatus

  • getAssetAttachmentUploadStatus(twinId: string, assetId: string, token: string, signal?: AbortSignal): Promise<UploadStatusGet>
  • Polls the in-memory upload-session cache for an attachment that's being uploaded.


    Parameters

    • twinId: string
    • assetId: string
    • token: string
    • optionalsignal: AbortSignal

    Returns Promise<UploadStatusGet>

getAssetCategory

  • getAssetCategory(categoryId: string, signal?: AbortSignal): Promise<AssetCategoryGet>
  • @throws

    When the category does not exist (404).


    Parameters

    • categoryId: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetCategoryGet>

getAssetGroup

  • getAssetGroup(name: string, signal?: AbortSignal): Promise<AssetGroupGet>
  • Returns one default group by its stable name, case-insensitively.

    @throws

    The name is one of the three but its group has not been seeded for this customer yet — safe to retry (404).

    @throws

    The name is not one of the three; retrying will not help (404).

    @throws

    The caller does not hold ManageAssetPermissions (403).

    @throws

    No valid auth context (401).

    @throws

    The title could not be resolved (503); safe to retry unchanged.


    Parameters

    • name: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetGroupGet>

getAssetType

  • getAssetType(categoryId: string, typeId: string, signal?: AbortSignal): Promise<AssetTypeGet>
  • @throws

    When the category or type does not exist (404).


    Parameters

    • categoryId: string
    • typeId: string
    • optionalsignal: AbortSignal

    Returns Promise<AssetTypeGet>

getAssetTypeCatalog

  • Returns the customer's asset-type catalog: categories nested with their latest non-deleted types and full metadata schemas inline. One round-trip is enough to populate a picker dropdown and render any per-type metadata form.


    Parameters

    • optionalsignal: AbortSignal

    Returns Promise<AssetCatalogResponse>

getAssetTypeMetaSchema

  • getAssetTypeMetaSchema(signal?: AbortSignal): Promise<Record<string, unknown>>
  • Returns the Twinfinity meta-schema document — the JSON Schema describing valid asset-type metadata schemas. The bytes the backend itself validates against, served verbatim. Power-user tools (Monaco-backed JSON editors, schema-aware tooling) fetch this at runtime so their in-editor diagnostics line up with what the server will accept, decoupled from the FE bundle's build time.


    Parameters

    • optionalsignal: AbortSignal

    Returns Promise<Record<string, unknown>>

getMyPermissions

  • Returns the caller's named, customer-scoped capabilities against the Twin service — the asset-domain vocabulary ViewAssets, EditAssets, DeleteAssets, EditAssetTypes and ManageAssetPermissions. The admin app uses this to enable or disable buttons instead of letting the user click through to a 403.

    No client-side cache — every call hits the wire. Underlying scope grants don't shift within a session, so callers are expected to memoise the result themselves (e.g. via React Query / a once-on-mount fetch) rather than calling this on every render.

    Throws TwinUnauthenticatedError on 401 (no valid auth context; caller should redirect to login). Returns an empty permissions array on 403 (authenticated but no Twin-service capabilities). Unknown capability strings should be ignored — adding a new capability is a non-breaking change.

    A 503 throws rather than answering with an empty array: the Permission service gave no answer, so the capabilities are unknown rather than absent, and the call is safe to retry unchanged.


    Parameters

    • optionalsignal: AbortSignal

    Returns Promise<MyPermissions>

getMyTwinPermissions

  • getMyTwinPermissions(twinId: string, signal?: AbortSignal): Promise<MyTwinPermissions>
  • Returns the capabilities the caller holds on one specific twin. Open to every authenticated caller — an empty list is an honest answer rather than a refusal — so a UI can gate its controls on this before it knows anything about the caller.

    The answer mixes vocabularies: the twin's own TwinScopedCapability values, plus the asset-instance capabilities ViewAssets, EditAssets and DeleteAssets, which gate the assets hanging off this twin. The catalog capabilities and ManageAssetPermissions are not twin-bound and are absent here.

    Distinct from getMyPermissions, which answers the customer-scoped question over the whole asset domain. That one returns an empty list on 403; this route has no capability gate to refuse at, so a 403 here means something outside the Twin service refused, and is thrown.

    @throws

    The twin does not exist, or the caller cannot see it — the surface does not distinguish the two.

    @throws

    No valid auth context (401).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • twinId: string
    • optionalsignal: AbortSignal

    Returns Promise<MyTwinPermissions>

getProcessorEvents

  • getProcessorEvents(twinId: string, twinVersion: number, processorId: string, offset?: number, limit?: number, signal?: AbortSignal): Promise<PaginatedResponse<TwinProcessorEvent>>
  • @throws

    On invalid query parameters (400).

    @throws

    When the processor does not exist for this twin version (404).


    Parameters

    • twinId: string
    • twinVersion: number
    • processorId: string
    • offset: number = 0
    • limit: number = 100
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<TwinProcessorEvent>>

getTwin

  • getTwin(twin: string | { id: string; version: number }, signal?: AbortSignal): Promise<TwinGet>
  • @throws

    When the twin or version does not exist (404).


    Parameters

    • twin: string | { id: string; version: number }

      Twin ID string, or {id, version} to fetch a specific version.

      • id: string
      • version: number
    • optionalsignal: AbortSignal

    Returns Promise<TwinGet>

getTwinContent

  • Returns content for the latest twin version.

    @throws

    When the twin does not exist (404).


    Parameters

    • twinId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinVersionContentResponse>

getTwinDiagnostics

  • @throws

    When the twin does not exist (404).


    Parameters

    • twinId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinDiagnosticsResponse>

getTwinFile

  • getTwinFile(twinId: string, fileId: string, signal?: AbortSignal): Promise<TwinFileGet>
  • @throws

    When the file does not exist (404).

    @throws

    On invalid request (400).


    Parameters

    • twinId: string
    • fileId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinFileGet>

getTwinFileContent

  • getTwinFileContent(twinId: string, fileId: string, signal?: AbortSignal): Promise<Blob>
  • @throws

    When the file does not exist (404).


    Parameters

    • twinId: string
    • fileId: string
    • optionalsignal: AbortSignal

    Returns Promise<Blob>

getTwinFileVersion

  • getTwinFileVersion(twinId: string, fileId: string, version: number, signal?: AbortSignal): Promise<TwinFileGet>
  • @throws

    When the file or version does not exist (404).


    Parameters

    • twinId: string
    • fileId: string
    • version: number
    • optionalsignal: AbortSignal

    Returns Promise<TwinFileGet>

getTwinFileVersionContent

  • getTwinFileVersionContent(twinId: string, fileId: string, version: number, signal?: AbortSignal): Promise<Blob>
  • @throws

    When the file or version does not exist (404).


    Parameters

    • twinId: string
    • fileId: string
    • version: number
    • optionalsignal: AbortSignal

    Returns Promise<Blob>

getTwinGroup

  • getTwinGroup(twinId: string, groupId: string, signal?: AbortSignal): Promise<TwinGroupGet>
  • Returns one of the twin's own default groups.

    @throws

    The twin does not own this group — thrown even when the group exists in the tenant and holds capabilities on this twin, since ownership, not existence, is what this route answers (404).

    @throws

    The twin does not exist or the caller cannot see it (404).

    @throws

    ManageTwinPermissions is required (403).

    @throws

    ScopesNotProvisioned (409).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • twinId: string
    • groupId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinGroupGet>

getTwinVersionContent

  • @throws

    When the twin or version does not exist (404).


    Parameters

    • twinId: string
    • twinVersion: number
    • optionalsignal: AbortSignal

    Returns Promise<TwinVersionContentResponse>

getTwinVersionDiagnostics

  • getTwinVersionDiagnostics(twinId: string, twinVersion: number, signal?: AbortSignal): Promise<TwinDiagnosticsResponse>
  • @throws

    When the twin or version does not exist (404).


    Parameters

    • twinId: string
    • twinVersion: number
    • optionalsignal: AbortSignal

    Returns Promise<TwinDiagnosticsResponse>

getTwinVersionEvents

  • @throws

    On invalid query parameters (400).

    @throws

    When the twin or version does not exist (404).


    Parameters

    • twinId: string
    • twinVersion: number
    • offset: number = 0
    • limit: number = 100
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<TwinProcessorEvent>>

listAllAssetPermissions

  • Every entry of listAssetPermissions, paged to exhaustion.


    Parameters

    • optionalsignal: AbortSignal

    Returns Promise<AssetPrincipalPermissionsGet[]>

listAllTwinPermissions

  • Every permission entry on the twin, following the pagination to the end. The whole access-control list of one twin is a handful of entries, and reviewing it is the point of the surface, so this — rather than listTwinPermissions — is what most callers want.

    Throws whatever listTwinPermissions throws, from whichever page hit it.


    Parameters

    • twinId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinPrincipalPermissionsGet[]>

listAllTwins

  • listAllTwins(options?: { includeDeleted?: boolean; relatedTo?: string }, signal?: AbortSignal): Promise<ListTwinItem[]>
  • listAllTwins(relatedTo?: string, signal?: AbortSignal): Promise<ListTwinItem[]>
  • Fetches all twins by auto-paginating through listTwins. Caps at 1000 pages.


    Parameters

    • optionaloptions: { includeDeleted?: boolean; relatedTo?: string }

      relatedTo filters by container ID; includeDeleted includes soft-deleted twins (returned redacted, default false).

      • optionalincludeDeleted: boolean
      • optionalrelatedTo: string
    • optionalsignal: AbortSignal

    Returns Promise<ListTwinItem[]>

listAssetAttachments

  • listAssetAttachments(twinId: string, assetId: string, options?: { includeDeleted?: boolean; limit?: number; offset?: number; page?: string }, signal?: AbortSignal): Promise<PaginatedResponse<AttachmentGet>>
  • Lists attachments for a single asset.


    Parameters

    • twinId: string
    • assetId: string
    • optionaloptions: { includeDeleted?: boolean; limit?: number; offset?: number; page?: string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionaloffset: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AttachmentGet>>

listAssetCategories

  • @throws

    On invalid query parameters (400).


    Parameters

    • optionaloptions: { includeDeleted?: boolean; limit?: number; page?: string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetCategoryGet>>

listAssetCategoryVersions

  • listAssetCategoryVersions(categoryId: string, options?: { includeDeleted?: boolean; limit?: number; page?: string }, signal?: AbortSignal): Promise<PaginatedResponse<AssetCategoryGet>>
  • Returns every version of a single asset category, newest first. Mirrors listAssetTypeVersions and twin.get_twin_versions.

    @throws

    When the category's header row does not exist (404).


    Parameters

    • categoryId: string
    • optionaloptions: { includeDeleted?: boolean; limit?: number; page?: string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetCategoryGet>>

listAssetGroups

  • Returns the asset domain's default groups — AssetsReaders, AssetsContributors, AssetsAdministrators — under the ids whose membership confers their preset capabilities.

    A group whose seeding has not completed for this customer is omitted rather than listed under a placeholder title, so a short list is a state to poll rather than an error.

    @throws

    The caller does not hold ManageAssetPermissions (403).

    @throws

    No valid auth context (401).

    @throws

    The titles could not be resolved (503); safe to retry unchanged.


    Parameters

    • optionalsignal: AbortSignal

    Returns Promise<AssetGroupsGet>

listAssetPermissions

  • Lists one page of the principals holding capabilities on the customer-wide asset domain, with the capabilities each of them holds. The companion administration surface to getMyPermissions, which answers only for the caller.

    pagination.nextPage is emitted unconditionally — it is non-null on the last page too — so it is not a termination signal. Page until a response comes back with fewer entries than the limit asked for, or use listAllAssetPermissions, which does that. On an access-review surface, stopping early under-reports who holds capabilities.

    @throws

    The caller does not hold ManageAssetPermissions (403).

    @throws

    The limit is out of range, or the pagination token is invalid (400).

    @throws

    No valid auth context (401).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • optionaloptions: { limit?: number; page?: string }
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetPrincipalPermissionsGet>>

listAssetTypeVersions

  • listAssetTypeVersions(categoryId: string, typeId: string, options?: { includeDeleted?: boolean; limit?: number; page?: string }, signal?: AbortSignal): Promise<PaginatedResponse<AssetTypeGet>>
  • Returns every version of a single asset type, newest first. Mirrors twin.get_twin_versions.

    @throws

    When the type's header row does not exist (404).


    Parameters

    • categoryId: string
    • typeId: string
    • optionaloptions: { includeDeleted?: boolean; limit?: number; page?: string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetTypeGet>>

listAssetTypes

  • listAssetTypes(categoryId: string, options?: { includeDeleted?: boolean; limit?: number; page?: string }, signal?: AbortSignal): Promise<PaginatedResponse<AssetTypeGet>>
  • @throws

    On invalid query parameters (400).


    Parameters

    • categoryId: string
    • optionaloptions: { includeDeleted?: boolean; limit?: number; page?: string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetTypeGet>>

listAssets

  • listAssets(twinId: string, offset?: number, limit?: number, options?: { includeDeleted?: boolean }, signal?: AbortSignal): Promise<PaginatedResponse<AssetListItem>>
  • @throws

    On invalid query parameters (400).

    @throws

    When the twin does not exist (404).


    Parameters

    • twinId: string
    • offset: number = 0
    • limit: number = 100
    • optionaloptions: { includeDeleted?: boolean }
      • optionalincludeDeleted: boolean
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<AssetListItem>>

listTwinFileVersions

listTwinFiles

listTwinGroups

  • listTwinGroups(twinId: string, signal?: AbortSignal): Promise<TwinGroupsGet>
  • Returns the three default groups the twin owns — TwinReaders, TwinContributors, TwinAdministrators — under the ids to name in setTwinPermissions.

    Not a picker for the principals a twin can be granted to: that is every group in the tenant, which the Permission service lists. These are the groups the twin itself owns, whose membership confers its preset capability levels.

    @throws

    ManageTwinPermissions is required (403).

    @throws

    The twin does not exist or the caller cannot see it (404).

    @throws

    ScopesNotProvisioned (409).

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • twinId: string
    • optionalsignal: AbortSignal

    Returns Promise<TwinGroupsGet>

listTwinPermissions

  • Lists one page of the permission entries on every scope the twin owns. Each entry carries the etag of the scope it lives on, which is the value to send back when mutating that principal.

    pagination.nextPage is emitted unconditionally — it is non-null on the last page too — so it is not a termination signal. Page until a response comes back with fewer entries than the limit asked for, or use listAllTwinPermissions, which does that. On an access-review surface, stopping early under-reports who holds capabilities on the twin.

    @throws

    The caller may see the twin but does not hold ManageTwinPermissions on it (403).

    @throws

    The twin does not exist or the caller cannot see it (404).

    @throws

    The limit is out of range, or the pagination token is invalid or does not match the query it was issued for (400).

    @throws

    ScopesNotProvisioned — the twin owns no Twinfinity scope, so there is no permission state to read (409). Retrying will not help.

    @throws

    The request could not be completed (503); safe to retry unchanged.


    Parameters

    • twinId: string
    • optionaloptions: { limit?: number; page?: string }
      • optionallimit: number
      • optionalpage: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<TwinPrincipalPermissionsGet>>

listTwinVersions

  • listTwinVersions(id: string, options?: { includeDeleted?: boolean; limit?: number; page: undefined | string }, signal?: AbortSignal): Promise<PaginatedResponse<ListTwinItem>>
  • @throws

    On invalid query parameters (400).


    Parameters

    • id: string
    • optionaloptions: { includeDeleted?: boolean; limit?: number; page: undefined | string }
      • optionalincludeDeleted: boolean
      • optionallimit: number
      • page: undefined | string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<ListTwinItem>>

listTwins

  • @throws

    On invalid query parameters (400).


    Parameters

    • optionaloptions: { includeDeleted?: boolean; limit?: number; page?: string; relatedTo?: string }

      relatedTo filters by container ID; includeDeleted includes soft-deleted twins (returned redacted, default false); page/limit control pagination.

      • optionalincludeDeleted: boolean
      • optionallimit: number
      • optionalpage: string
      • optionalrelatedTo: string
    • optionalsignal: AbortSignal

    Returns Promise<PaginatedResponse<ListTwinItem>>

loadGeometryInfo

  • Downloads and deserializes geometry info (t8gi) using default types. When no version is specified, searches versions newest-first for one containing t8gi content.

    @throws

    When no version has t8gi content.


    Parameters

    • twin: string | { id: string; version: number }

      Twin ID string, or {id, version} to load a specific version.

      • id: string
      • version: number
    • optionalsignal: AbortSignal

    Returns Promise<TwinGeometryInfo<T8GIMeshDescriptor, T8GIStyle, T8GIRegion>>

loadGeometryInfoWithFactories

  • loadGeometryInfoWithFactories<TMeshDescriptor, TStyle, TRegion>(twin: string | { id: string; version: number }, meshDescriptorFactory: (dto: T8GIMeshDescriptorDTO) => TMeshDescriptor, styleFactory: (dto: T8GIStyleDTO) => TStyle, regionFactory: (dto: T8GIRegionDTO) => TRegion, signal?: AbortSignal): Promise<TwinGeometryInfo<TMeshDescriptor, TStyle, TRegion>>
  • Downloads and deserializes geometry info (t8gi) using custom factory functions. When no version is specified, searches versions newest-first for one containing t8gi content.

    @throws

    When no version has t8gi content.


    Type parameters

    • TMeshDescriptor
    • TStyle
    • TRegion

    Parameters

    • twin: string | { id: string; version: number }

      Twin ID string, or {id, version} to load a specific version.

      • id: string
      • version: number
    • meshDescriptorFactory: (dto: T8GIMeshDescriptorDTO) => TMeshDescriptor
      • styleFactory: (dto: T8GIStyleDTO) => TStyle
        • regionFactory: (dto: T8GIRegionDTO) => TRegion
          • optionalsignal: AbortSignal

          Returns Promise<TwinGeometryInfo<TMeshDescriptor, TStyle, TRegion>>

        loadTwin

        • loadTwin(twin: string | { id: string; version: number }, signal?: AbortSignal): Promise<Twin<T8Project<T8Product<T8EntityType<T8Unit>, T8Unit>, T8Unit>, T8Product<T8EntityType<T8Unit>, T8Unit>, T8EntityType<T8Unit>, T8Unit>>
        • Downloads and deserializes the T8 client model (t8cm + t8cm-ext) using default types. When no version is specified, searches versions newest-first for one containing t8cm content.

          @throws

          When no version has t8cm content.


          Parameters

          • twin: string | { id: string; version: number }

            Twin ID string, or {id, version} to load a specific version.

            • id: string
            • version: number
          • optionalsignal: AbortSignal

          Returns Promise<Twin<T8Project<T8Product<T8EntityType<T8Unit>, T8Unit>, T8Unit>, T8Product<T8EntityType<T8Unit>, T8Unit>, T8EntityType<T8Unit>, T8Unit>>

        loadTwinWithFactories

        • loadTwinWithFactories<TProject, TProduct, TEntityType, TUnit>(twin: string | { id: string; version: number }, projectFactory: (dto: T8ClientProjectDTO<TUnit>) => TProject, productFactory: (dto: T8ClientProductDTO<TUnit>) => TProduct, entityTypeFactory: (dto: T8ClientEntityTypeDTO<TUnit>) => TEntityType, unitFactory: (dto: T8ClientUnitDTO, dataModel: T8ClientModelDTO) => TUnit, connectProject: (dto: T8ClientProjectConnectionsDTO<TProduct>, project: TProject) => void, connectProduct: (dto: T8ClientProductConnectionsDTO<TProduct, TEntityType>, product: TProduct) => void, signal?: AbortSignal): Promise<Twin<TProject, TProduct, TEntityType, TUnit>>
        • Downloads and deserializes the T8 client model using custom factory functions for domain-specific types. When no version is specified, searches versions newest-first for one containing t8cm content.

          @throws

          When no version has t8cm content.


          Type parameters

          • TProject
          • TProduct
          • TEntityType
          • TUnit

          Parameters

          • twin: string | { id: string; version: number }

            Twin ID string, or {id, version} to load a specific version.

            • id: string
            • version: number
          • projectFactory: (dto: T8ClientProjectDTO<TUnit>) => TProject
            • productFactory: (dto: T8ClientProductDTO<TUnit>) => TProduct
              • entityTypeFactory: (dto: T8ClientEntityTypeDTO<TUnit>) => TEntityType
                • unitFactory: (dto: T8ClientUnitDTO, dataModel: T8ClientModelDTO) => TUnit
                  • connectProject: (dto: T8ClientProjectConnectionsDTO<TProduct>, project: TProject) => void
                    • connectProduct: (dto: T8ClientProductConnectionsDTO<TProduct, TEntityType>, product: TProduct) => void
                      • optionalsignal: AbortSignal

                      Returns Promise<Twin<TProject, TProduct, TEntityType, TUnit>>

                    loadTwinWithGeometry

                    • loadTwinWithGeometry(twin: string | { id: string; version: number }, signal?: AbortSignal): Promise<Twin<T8ProjectWithGeometry, T8ProductWithGeometry<T8EntityType<T8Unit>>, T8EntityType<T8Unit>, T8Unit>>
                    • Downloads and deserializes both the client model (t8cm) and geometry (t8gi/t8gd) into a combined result. When no version is specified, searches versions newest-first for one containing both t8cm and t8gi content.

                      @throws

                      When no version has both t8cm and t8gi content.


                      Parameters

                      • twin: string | { id: string; version: number }

                        Twin ID string, or {id, version} to load a specific version.

                        • id: string
                        • version: number
                      • optionalsignal: AbortSignal

                      Returns Promise<Twin<T8ProjectWithGeometry, T8ProductWithGeometry<T8EntityType<T8Unit>>, T8EntityType<T8Unit>, T8Unit>>

                    putAssetAttachment

                    • Updates an attachment's description / soft-delete flag. documentId is immutable — rebinding is rejected.

                      @throws

                      On etag mismatch (409). The error's currentAttachment carries the server's current state.

                      @throws

                      When the attachment does not exist (404).


                      Parameters

                      • twinId: string
                      • assetId: string
                      • attachmentId: string
                      • body: AssetAttachmentPut
                      • optionalsignal: AbortSignal

                      Returns Promise<AttachmentGet>

                    putAssetCategory

                    • Upserts an asset category. Provide an empty/missing etag for first writes and the existing etag to update.

                      @throws

                      On invalid request body (400).

                      @throws

                      On etag mismatch (409). The error's currentCategory contains the server's current state.


                      Parameters

                      Returns Promise<AssetCategoryGet>

                    putAssetType

                    • Upserts an asset type. The metadata schema is validated against the Twinfinity meta-schema at the API boundary; invalid schemas surface as a 400 with cause: MetadataSchemaInvalid.

                      @throws

                      On invalid request body (400). The error's errorBody carries the structured cause.

                      @throws

                      On etag mismatch (409). The error's currentType contains the server's current state.


                      Parameters

                      • categoryId: string
                      • typeId: string
                      • body: AssetTypePut
                      • optionalsignal: AbortSignal

                      Returns Promise<AssetTypeGet>

                    restoreAsset

                    • restoreAsset(twinId: string, assetId: string, etag: string): Promise<AssetGet>
                    • @throws

                      When the asset does not exist (404).

                      @throws

                      On etag mismatch (409). The error's currentAsset contains the server's current state.


                      Parameters

                      • twinId: string
                      • assetId: string
                      • etag: string

                      Returns Promise<AssetGet>

                    restoreAssetAttachment

                    • restoreAssetAttachment(twinId: string, assetId: string, attachmentId: string, etag: string, signal?: AbortSignal): Promise<AttachmentGet>
                    • Restores a soft-deleted attachment.

                      @throws

                      On etag mismatch (409).

                      @throws

                      When the attachment does not exist (404).


                      Parameters

                      • twinId: string
                      • assetId: string
                      • attachmentId: string
                      • etag: string
                      • optionalsignal: AbortSignal

                      Returns Promise<AttachmentGet>

                    restoreAssetCategory

                    • restoreAssetCategory(categoryId: string, etag: string, signal?: AbortSignal): Promise<AssetCategoryGet>
                    • Restores a soft-deleted category. Inserts a new asset_category_versions row with is_deleted=false; mirrors twin restore.

                      @throws

                      When the category does not exist (404).

                      @throws

                      On etag mismatch (409).


                      Parameters

                      • categoryId: string
                      • etag: string
                      • optionalsignal: AbortSignal

                      Returns Promise<AssetCategoryGet>

                    restoreAssetType

                    • restoreAssetType(categoryId: string, typeId: string, etag: string, signal?: AbortSignal): Promise<AssetTypeGet>
                    • Restores a soft-deleted type. Inserts a new asset_type_versions row with is_deleted=false; mirrors twin restore.

                      @throws

                      When the type does not exist (404).

                      @throws

                      On etag mismatch (409).


                      Parameters

                      • categoryId: string
                      • typeId: string
                      • etag: string
                      • optionalsignal: AbortSignal

                      Returns Promise<AssetTypeGet>

                    restoreTwin

                    • restoreTwin(twinId: string, etag: string, signal?: AbortSignal): Promise<TwinGet>
                    • @throws

                      When the twin does not exist (404).

                      @throws

                      On etag mismatch (409). The error's currentTwin contains the server's current state.


                      Parameters

                      • twinId: string
                      • etag: string
                      • optionalsignal: AbortSignal

                      Returns Promise<TwinGet>

                    restoreTwinFile

                    • restoreTwinFile(twinId: string, fileId: string, etag: string, signal?: AbortSignal): Promise<TwinFileGet>
                    • @throws

                      When the file does not exist (404).

                      @throws

                      On etag mismatch (409). The error's currentTwinFile contains the server's current state.

                      @throws

                      On invalid request (400).


                      Parameters

                      • twinId: string
                      • fileId: string
                      • etag: string
                      • optionalsignal: AbortSignal

                      Returns Promise<TwinFileGet>

                    setAssetPermissions

                    • Replaces what one principal holds on the asset domain. Capabilities absent from body.permissions are revoked, and an empty list revokes everything — leaving the principal with no listing entry at all, exactly as deleteAssetPermissions does.

                      body.etag is required whenever the principal already holds capabilities, and may be omitted only to create the grants of one that holds none.

                      @throws

                      No group in the tenant carries this id (404).

                      @throws

                      SystemPrincipalImmutable — a seeded default group, whose preset is conferred by membership rather than by writing here — or ManagePermissionsNotGrantableToAllAuthenticated (400).

                      @throws

                      EtagRequired or EtagMismatch (409), carrying the current state to retry from.

                      @throws

                      The caller does not hold ManageAssetPermissions (403).

                      @throws

                      No valid auth context (401).

                      @throws

                      The request could not be completed (503); safe to retry unchanged.


                      Parameters

                      Returns Promise<AssetPrincipalPermissionsGet>

                    setTwinPermissions

                    • Replaces the principal's capabilities on the twin, and returns the entry as stored along with the etag to chain the next write on. permissions: [] revokes all four capabilities without removing an entry that carries bits outside this vocabulary.

                      body.etag may be omitted only for a principal that holds nothing on the twin yet; see TwinPermissionsPut. Both etag refusals arrive as TwinPermissionsConflictError, carrying the current state to retry from.

                      @throws

                      The target is immutable through this surface — the twin's own default groups and the seeded system principals, marked by TwinPrincipalPermissionsGet.readOnly (cause SystemPrincipalImmutable) — or the write asked for ManageTwinPermissions on the all-authenticated principal (cause ManagePermissionsNotGrantableToAllAuthenticated), which would make the whole tenant an administrator of the twin (400).

                      @throws

                      No principal carries this id (404).

                      @throws

                      The twin does not exist or the caller cannot see it (404).

                      @throws

                      ManageTwinPermissions is required (403).

                      @throws

                      EtagRequired, EtagMismatch or ScopesNotProvisioned (409); the first two carry currentState.

                      @throws

                      The request could not be completed (503); safe to retry unchanged.


                      Parameters

                      Returns Promise<TwinPrincipalPermissionsGet>

                    updateAsset

                    • updateAsset(twinId: string, assetId: string, asset: AssetPut, signal?: AbortSignal): Promise<AssetGet>
                    • @throws

                      On invalid request body (400). The error's errorBody has structured detail.

                      @throws

                      On etag mismatch (409). The error's currentAsset contains the server's current state.


                      Parameters

                      • twinId: string
                      • assetId: string
                      • asset: AssetPut
                      • optionalsignal: AbortSignal

                      Returns Promise<AssetGet>

                    updateTwin

                    • updateTwin(twinId: string, twin: TwinPut, signal?: AbortSignal): Promise<TwinGet>
                    • Alias for createOrUpdateTwin.


                      Parameters

                      • twinId: string
                      • twin: TwinPut
                      • optionalsignal: AbortSignal

                      Returns Promise<TwinGet>

                    uploadAssetAttachmentFile

                    • Uploads a File / Blob to an existing upload session in one or more chunks, then resolves the upload token so the caller can poll getAssetAttachmentUploadStatus.


                      Parameters

                      Returns Promise<{ token: string }>