Usage examples

These examples use an authenticated sdk from Getting started. Run Kotlin calls in a coroutine and TypeScript calls in an async function. React hooks require SoliboProvider inside QueryClientProvider.

List the homes and residents of a housing community

A housing community (API: company) has sections (its homes and commercial units) and residents (the people and organisations with a role in it).

import no.solibo.oss.sdk.api.gen.models.OrganizationResident
import no.solibo.oss.sdk.api.gen.models.PersonResident

val sections = sdk.api.sections.indexSection(companyId = companyId).body()
sections.items.forEach { println("${it.hNr} ${it.identifier}") }

val residents = sdk.api.residents.indexResident(companyId = companyId).body()
residents.items.forEach { resident ->
    val name = when (resident) {
        is PersonResident -> resident.name.complete
        is OrganizationResident -> resident.name
    }
    println("$name: ${resident.roles?.map { it.type }}")
}
const sections = await sdk.api.sections.indexSection({ companyId })
sections.items.forEach(section => console.log(section.hNr, section.identifier))

const residents = await sdk.api.residents.indexResident({ companyId })
residents.items.forEach(resident => {
  const name = resident.type === 'solibo.residents.query.domain.PersonResident'
    ? resident.name.complete
    : resident.name
  console.log(name, resident.roles?.map(role => role.type.name))
})

In React, useSections({ companyId }) and useResidents({ companyId }) return the same lists as paged hooks.

hNr is the official dwelling number (bolignummer), for example H0301 (floor 03, unit 01); identifier is the housing community’s own display label. Each call returns the first page; see Paged lists for the rest.

Update a section

Pass the company ID in both the request and the command. The update field is hnr; create commands and responses use hNr.

import no.solibo.oss.sdk.api.gen.models.SectionType
import no.solibo.oss.sdk.api.gen.models.UpdateSectionCommand

sdk.api.sections.updateSection(
    companyId = companyId,
    sectionId = sectionId,
    updateSectionCommand = UpdateSectionCommand(
        companyId = companyId,
        sectionType = SectionType.BOLIG,
        hnr = "H0301",
        identifier = "A-301",
    ),
)
import { SectionType } from '@solibo/solibo-sdk'

await sdk.api.sections.updateSection({
  companyId,
  sectionId,
  input: { companyId, sectionType: SectionType.BOLIG, hnr: 'H0301', identifier: 'A-301' },
})

In React, the mutation hook takes the command as cmd:

import { SectionType, type Id } from '@solibo/solibo-sdk'
import { useUpdateSection } from '@solibo/solibo-react'

function UpdateSection({ companyId, sectionId }: { companyId: Id; sectionId: Id }) {
  const updateSection = useUpdateSection()

  return (
    <>
      <button
        disabled={updateSection.isPending}
        onClick={() => updateSection.mutate({
          companyId,
          sectionId,
          cmd: {
            companyId,
            sectionType: SectionType.BOLIG,
            hnr: 'H0301',
            identifier: 'A-301',
          },
        })}
      >
        Save section
      </button>
      {updateSection.isError && <p>Could not save the section.</p>}
    </>
  )
}

The hook refreshes related query caches after a successful change.

Document uploads

Uploading a document with progress (Kotlin)

Pass bytes and an optional progress callback:

import no.solibo.oss.sdk.SoliboSDK
import no.solibo.oss.sdk.api.UploadDocumentRequest
import no.solibo.oss.sdk.api.UploadProgress
import no.solibo.oss.sdk.api.gen.models.DocumentType

suspend fun uploadMeetingMinutes(
    sdk: SoliboSDK,
    companyId: Long,
    fileName: String,
    bytes: ByteArray,
) {
    val document =
        sdk.api.documents.uploadDocument(
            request = UploadDocumentRequest(
                companyId = companyId,
                documentType = DocumentType.MEETING,
                fileName = fileName,
                bytes = bytes,
                contentType = "application/pdf",
            ),
        ) { progress: UploadProgress ->
            println("Upload progress: ${(progress.fraction * 100).toInt()}%")
        }

    println("Uploaded document ${document.id} -> ${document.fileName}")
}

Uploading a private company document with the SDK facade (TypeScript)

For direct SDK calls, read the file into bytes:

import {
  DocumentType,
  SoliboClient,
} from '@solibo/solibo-sdk'

async function uploadMeetingMinutes(
  sdk: SoliboClient,
  companyId: number,
  file: File,
) {
  const bytes = new Int8Array(await file.arrayBuffer())

  const document = await sdk.api.documents.uploadDocument({
    request: {
      companyId,
      documentType: DocumentType.MEETING,
      fileName: file.name,
      bytes,
      contentType: file.type || undefined,
    },
    onUploadProgress: (progress) => {
      console.log(
        `Upload ${Math.round(progress.fraction * 100)}% (${progress.loaded}/${progress.total})`,
      )
    },
  })

  console.log(`Uploaded document ${document.id}`)
  return document
}

Uploading a file in React

import { useState } from 'react'
import { useUploadDocument } from '@solibo/solibo-react'
import { DocumentType } from '@solibo/solibo-sdk'

function UploadButton({ companyId, file }: { companyId: number; file: File }) {
  const uploadDocument = useUploadDocument()
  const [progress, setProgress] = useState(0)

  const handleUpload = async () => {
    await uploadDocument.mutateAsync({
      companyId,
      documentType: DocumentType.OTHER,
      file,
      onUploadProgress: ({ fraction }) => setProgress(Math.round(fraction * 100)),
    })
  }

  return (
    <>
      <button onClick={handleUpload} disabled={uploadDocument.isPending}>Upload document</button>
      <progress max={100} value={progress} />
      {uploadDocument.isError && <p>Upload failed. Try again.</p>}
    </>
  )
}

Upload multiple attachments in React

Use useMultiUploadDocument() with belongsToId for resource attachments, or with parentId for a document directory.

import { DocumentType } from '@solibo/solibo-sdk'
import { useMultiUploadDocument } from '@solibo/solibo-react'

function UploadAttachments(props: {
  companyId: number
  conversationId: number
  files: FileList
}) {
  const uploadDocuments = useMultiUploadDocument()

  const handleUpload = async () => {
    const files = Array.from(props.files)
    const results = await uploadDocuments.mutateAsync({
      companyId: props.companyId,
      documentType: DocumentType.CONVERSATION,
      belongsToId: props.conversationId,
      fileList: files,
      onUploadProgress: ({ file, fraction }) => {
        console.log(file.name, Math.round(fraction * 100))
      },
    })

    const failedFiles = results.flatMap((result, index) =>
      result.status === 'rejected' ? [files[index].name] : [],
    )
    console.log('Failed files:', failedFiles)
  }

  return <button onClick={handleUpload}>Upload attachments</button>
}

For an internal (board-only) conversation message, add visibility: 'INTERNAL'; otherwise the files are attached to the public conversation.

Results stay in file order; check each result’s status as described in Choosing a multi-file helper. For public conversations, use useMultiUploadPublicDocumentToConversation() with companySlug, conversationId, and fileList.

Query options without React

Use @solibo/solibo-query when your framework manages TanStack Query directly:

import { QueryClient } from '@tanstack/query-core'
import { companyByIdQueryOptions } from '@solibo/solibo-query'

const queryClient = new QueryClient()
const company = await queryClient.fetchQuery(
  companyByIdQueryOptions(sdk, { id: companyId }),
)

More recipes


Solibo AS