Skip to main content

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

If your own components import DailyVideo or Daily hooks, also install @daily-co/daily-react.

Quickstart

AkapuluProvider takes paths to your local API routes:
  • connectPath
  • updatesPath
The browser calls those local routes. Your server routes then call Akapulu APIs through @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:
  • AkapuluProvider
  • useAkapuluSession
  • useAkapuluEvents
  • useAkapuluDailyCall
  • useAkapuluMediaControls
  • useAkapuluParticipantRoles
  • useConnectChime
  • armConnectAudio
  • playConnectChime
  • AkapuluBotAudio
  • AkapuluConfig
  • AkapuluEvent

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.
While 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.
Import AkapuluConfig from @akapulu/react:
What is not on config:
  • No API key. Keep AKAPULU_API_KEY on the server.
  • No getAuthToken and no fetch interceptor. User auth is headers.
  • connectBody is JSON for your local connect route (for example patient_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:
Lifecycle & connection
  • 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 arms AudioContext during the Start Call click so useConnectChime() can play after a long boot.
  • error — when status is "error", structured details (code optional, message required) for your error UI or logging. If your local connect/updates route forwards the Akapulu JSON, code is the API error_code (for example QUOTA_EXCEEDED). Otherwise it may be the HTTP status string ("403") or a client code such as UPDATES_TIMEOUT.
Call readiness & updates (from your updates route) The SDK GETs this route only while 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 while status === "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.
Scenario / flow
  • currentNode — the active scenario node ({ key, label }) or null if none.
Transcript & bot
  • 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.
Correlation
  • conversationSessionId — Akapulu conversation session id from connect (used when polling updates; also useful if your app logs or links out to dashboard/API records).
See Customize Conversation UI for how this fits into a full custom layout with Daily and media helpers.

useConnectChime(enabled?)

Plays a short chime when session status goes connectingconnected (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:
Low-level helpers 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.
Use 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

When the session enters 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_changed
  • bot_speaking_state_changed
  • node_changed
  • tool_event
  • transcript_updated
  • call_ready
  • timeout
See Callbacks and events for the full breakdown.

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
If you want a prebuilt conversation UI instead, use React UI.