Overview
@akapulu/react is the lower-level React package in the Akapulu Web SDK.
It gives you the provider, hooks, and media helpers you need to build your own React conversation UI.
Installation
DailyVideo or Daily hooks, also install @daily-co/daily-react.
Quickstart
AkapuluProvider takes paths to your local API routes:
connectPathupdatesPath
@akapulu/server. Keep the API key on the server, and authenticate users on your connect route before starting a call. Pass user auth with config.headers (object or a function called when the request is sent).
Main exports
The public exports currently include:AkapuluProvideruseAkapuluSessionuseAkapuluEventsuseAkapuluDailyCalluseAkapuluMediaControlsuseAkapuluParticipantRolesuseConnectChimearmConnectAudioplayConnectChimeAkapuluBotAudioAkapuluConfigAkapuluEvent
Provider
AkapuluProvider wraps your app and creates the conversation session store.
AkapuluConfig includes:
string
required
Local connect endpoint called by the browser.
string
required
Local updates endpoint called by the browser.
object | (() => object | Promise<object>)
Optional JSON payload forwarded to your local connect route. Pass an object, or a function that is called when connect is requested (not when the provider mounts).
object | (() => object | Promise<object>)
Optional headers on your local connect POST and updates GET. Pass an object, or a function that is called when each request is sent. Use this to authenticate users on those routes.
number
Optional interval for polling your local updates route while the avatar boots. Default is 200ms. Polling stops once the call is ready. Live transcripts and speaking state then come from Daily, not this route.
status === "connecting", the React SDK waits up to 200 seconds for the backend to report that the call is ready.
If the updates route never reports call_is_ready: true within that window, the session transitions to:
status: "error"error.code: "UPDATES_TIMEOUT"error.message: "Timed out waiting for assistant to become ready."
AkapuluTransport
Optional custom transport implementation.
AkapuluConfig from @akapulu/react:
config:
- No API key. Keep
AKAPULU_API_KEYon the server. - No
getAuthTokenand no fetch interceptor. User auth isheaders. connectBodyis JSON for your local connect route (for examplepatient_id). Do not put secrets there.
connectBody and headers are read when each request is sent, so a function (or a later object) can pick up a fresh token. endpoints and transport are taken from the first mount; changing those later does not recreate the session.
Ending a call: When your user ends the call in your app, call end() from useAkapuluSession(). That leaves the Daily room from the browser and runs the SDK teardown so the session is no longer live. If the assistant disconnects from Daily first, AkapuluProvider calls end() for you so status does not stay connected with no assistant in the room.
Hooks
useAkapuluSession()
Call useAkapuluSession() anywhere under AkapuluProvider. It exposes everything in the session store plus start / end:
status— where the client is in the join/leave flow:"idle"→"connecting"→"connected"→"disconnecting"/"ended", or"error"if something failed.start/end— async actions that begin the conversation (connect + Daily join) or hang up and reset session state.start()also armsAudioContextduring the Start Call click souseConnectChime()can play after a long boot.error— whenstatusis"error", structured details (codeoptional,messagerequired) for your error UI or logging. If your local connect/updates route forwards the Akapulu JSON,codeis the APIerror_code(for exampleQUOTA_EXCEEDED). Otherwise it may be the HTTP status string ("403") or a client code such asUPDATES_TIMEOUT.
status === "connecting" and the call is not ready yet. It does not poll for the rest of the call. Use config.headers on those GETs if you authenticate users on that route.
callIsReady— whether the backend considers the call ready (often used whilestatus === "connecting"so you are not stuck on a spinner forever).completionPercent— numeric progress through the scenario (0–100).latestUpdateText— short human-readable status line for loading/progress copy.
currentNode— the active scenario node ({ key, label }) ornullif none.
transcripts— ordered list of rows (id,text,speaker,timestamp,isFinal) for your own transcript UI.botSpeakingState—"idle","speaking", or"listening"for indicators or turn-taking UI.
conversationSessionId— Akapulu conversation session id from connect (used when polling updates; also useful if your app logs or links out to dashboard/API records).
useConnectChime(enabled?)
Plays a short chime when session status goes connecting → connected (the loading screen ends). start() already arms AudioContext during the user gesture. Pass false to disable. The chime is skipped when prefers-reduced-motion: reduce.
AkapuluConversation calls this hook for you (default on). In a custom UI, call it under AkapuluProvider:
armConnectAudio and playConnectChime are also exported if you need to arm from a custom Start Call button that does not go through start().
useAkapuluEvents(listener)
Subscribes to the normalized AkapuluEvent stream.
See Callbacks and events.
useAkapuluParticipantRoles(options?)
Returns participant-role mapping helpers for Daily sessions under AkapuluProvider.
Use this hook when your call may include more than one remote participant and you want a stable assistant video participant id instead of relying on participant order.
useAkapuluParticipantRoles for the assistant tile and useDaily() for the local/self tile:
useAkapuluMediaControls()
Returns media control helpers for the underlying Daily call.
useAkapuluDailyCall()
Returns the active Daily call object for the current session—the same DailyCall instance AkapuluProvider wires into Daily’s DailyProvider. Before the client exists, this hook returns null.
For most React UI you should use @daily-co/daily-react under AkapuluProvider; useDaily() reads that call object from context and is the usual way to drive video tiles, participants, and tracks. Use useAkapuluDailyCall() when you want the call object reference directly (for example code aligned with Daily call-object methods without importing useDaily).
Main unions and types
SessionStatus
status: "error", the SDK disconnects from the active Daily call and clears the active session state before surfacing the error to your UI.
BotSpeakingState
AkapuluEvent
The main event union includes:
status_changedbot_speaking_state_changednode_changedtool_eventtranscript_updatedcall_readytimeout
When to use this package
Use@akapulu/react when you want to:
- build your own layout
- render your own transcript UI
- control how tool events appear
- own your call controls and post-call flow

