SDK Reference
@health-universe/react exposes typed React Query hooks grouped by clinical domain, plus a generic escape hatch (useApiQuery / useApiMutation / api) for any scoped operation that doesn't yet have a first-class hook.
Every hook's arguments and return type are inferred from the generated client, so the bundled TypeScript declarations (@health-universe/react ships .d.ts) are the canonical source of truth — your editor's autocomplete is the fastest reference.
Org id vs workspace slug. Two different identifiers address the organization, and mixing them up is the most common mistake. Both come from
useHealthUniverseAuth().organization(see Auth):
Org id (
org_…,organization.id) — used by org-scoped hooks as a query param:usePatients({ organizationId }),useRoutines(organizationId),useOrgRoutineRuns(organizationId). (Org-scoped hooks also default to the provider's active org, so you often don't pass it.)Workspace slug (e.g.
acme-health,organization.slug) — used by workspace-scoped hooks as a path param:useSources(slug),useBundleDetail(slug, bundleId).If a workspace-scoped hook returns nothing, check the slug and your org membership first.
Auth
The SDK manages Clerk internally — you never import @clerk/clerk-react. It loads Clerk's official script from Clerk's CDN at runtime (the same way @clerk/clerk-react does), so the prebuilt widgets are fully styled. Read sign-in state and the active organization, and trigger sign-in/out/org-switching, through the SDK.
import { useHealthUniverseAuth, SignedIn, SignedOut, OrganizationSwitcher, UserButton } from '@health-universe/react'
function Header() {
const { isSignedIn, user, organization } = useHealthUniverseAuth()
return (
<header>
<OrganizationSwitcher /> {/* Clerk's prebuilt widget, via clerk-js */}
<UserButton />
</header>
)
}
// Gate UI on sign-in state:
<SignedIn><App /></SignedIn>
<SignedOut><SignInScreen /></SignedOut>useHealthUniverseAuth() returns:
isLoaded,isSignedInuser— the signed-in user (id + display fields)organization— the active org as{ id, slug, name }(the source of both the org id and the workspace slug above), ornullorganizations— the user's org memberships, for a custom switchersignIn(),signOut(),setActiveOrg(organizationId)
Components: <SignedIn> / <SignedOut> gate on sign-in state; <OrganizationSwitcher> / <UserButton> render Clerk's prebuilt, styled widgets (use useWorkspace().isPinned to hide the switcher in a pinned app). See Your First App for provider setup.
Locked by platform policy. These widgets are pinned to a deployed app's scope and can't be unlocked by props:
<OrganizationSwitcher>is switch-only (no personal workspace, no Create/Manage organization) and<UserButton>hides "Manage account" (Sign out stays). The org slug for workspace-scoped hooks still comes fromuseHealthUniverseAuth().organization.slug. The hiding is a UI lock — for an airtight boundary, also disable org creation and restrict the manage/account permissions in the Clerk Dashboard.
Patients
The full set:
usePatients(params, options)— list / search the org's patientsusePatient(id)— a single patientuseCreatePatient(),useUpdatePatient(),useDeletePatient()useUpsertPatientByExternalId()— idempotent EHR sync, keyed by your external id
Documents
The full set:
useDocumentSearch()— structured searchuseSemanticDocumentSearch()— semantic search (e.g.{ body: { query: 'aml relapse', threadId } })useDocumentTextSearch()— text searchuseDocumentStatus(id),useDocumentStatuses()— status by document, or by thread/patientuseDocumentChunks(id)— a document's extracted text, returned as ordered chunksuseExportDocument()
Render a document's text by sorting its chunks:
Routines & runs
The full set:
useRoutines(orgId),useRoutine(id)— list/read routines (name, description,steps[]pipeline,inputs[])useCreateRoutine(),useUpdateRoutine(),useDeleteRoutine(),useDiscoverRoutines()Routine-secret hooks
useTriggerRoutine()— start a run; returns the newrun_iduseRoutineRun(runId)— a single run, with terminal-aware polling (default 3s, stops at a terminal status)useRoutineRuns(routineId),useOrgRoutineRuns(orgId)— run historyuseRetryRun(),useCreateRunThread(),useDeleteRunThread()
A run's generated documents live on each step's output_artifacts as an A2A artifact array — [{ name, parts: [{ kind: 'text', text }] }]:
Generated text often embeds citation tags like
<file name="x.pdf">x.pdf</file>.react-markdownwon't render raw HTML, so strip or transform those before rendering.
Sources (bundles) & run review
useSources and useBundleDetail are workspace-scoped — they take the org slug as a path param, not the org id.
A routine run carries its source bundle on trigger_context.bundle_id. To build a full run-review surface, pair:
useRoutineRun(id)— steps +output_artifacts(the generated documents), anduseBundleDetail(slug, bundleId)— the input documents + patient the run started from.
See the react-starter RunView for a worked example.
Chat threads
Navigator threads are where context documents live.
The full set: useThreads, useThread, useCreateThread, useUpdateThread, useDeleteThread.
Other clinical domains
These domains are available as hooks and/or through the escape hatch below:
Providers —
useProviders,useProvider,useCreateProvider,useUpsertProviderByNpiRosters —
useRosters,useRoster,useRosterPatients, …Appointments —
useAppointments, …Connectors —
useEnabledConnectorsClinical tools —
useAutofillForm,useExecuteTool,useGenerateFormSchema,useSuggestTools
Any endpoint, fully typed — useApiQuery / useApiMutation
useApiQuery / useApiMutationEvery scoped operation can be turned into a typed query or mutation without a bespoke hook. Domains that don't yet have first-class hooks (providers, rosters, appointments, clinical tools, connectors, bundles) are reachable this way today. Options and the returned data type are inferred from the operation.
api is the generated SDK for the scoped surface only. You can also grab the raw client with useHealthUniverseClient() and call api.* imperatively.
Invalidating queries & realtime
Query-key factories are exported so you can invalidate after a mutation or an out-of-band update: patientKeys, runKeys, documentKeys, sourceKeys, threadKeys, and so on.
For run progress, useRoutineRun already polls (default 3s) and stops at a terminal status. The SDK does not bundle Supabase — for sub-second updates, supply your own subscription and invalidate the relevant query (runKeys.detail(runId), patientKeys.list(...), etc.).
Scope
The client is intentionally limited to the clinical domains above (routines, documents, patients, providers, rosters, appointments, sources/bundles, chat threads, clinical tools, connectors). Admin, deployments, billing, and internal tooling are not part of this package and cannot be called through it.
Last updated
Was this helpful?