@fluxyte/sdk
v0.8.1
Published
Official Fluxyte SDK (TypeScript) for the Fluxyte Onboarding AI API
Readme
Fluxyte SDK (TypeScript)
The official TypeScript SDK for the Fluxyte Onboarding AI API: a context-aware, documentation-grounded assistant designed for onboarding and setup flows (not generic chat).
Unreleased
- Chat and voice now use top-level
sessionIdoruserId; their context is optional. PublicChatContextcontains only validated catalogue/step hints, diagnostics, runtime metadata, locale, and timezone.- Structured
errorandattemptedActionobjects provide richer troubleshooting context. - Named public context, request, response, diagnostic, and event types are exported from all entrypoints.
What's New In 0.7.0
- Product Catalogue offering cards now expose optional
imageAltandvideoUrlfields. - Use
imageAltwhen rendering catalogue images and openvideoUrlas a validated hosted-video destination. - Existing
imageUrl, pricing, availability, and Commerce action fields remain backward compatible.
const response = await client.chat({
message: "Show me your plans",
sessionId: "session_123",
});
for (const offering of response.commerce?.offerings ?? []) {
console.log(offering.imageUrl, offering.imageAlt, offering.videoUrl);
}What's New In 0.6.0
- Product Catalogue responses now include typed
commercepresentation data. - Commerce presentations contain products/services offerings, prices, availability, features, and safe action IDs.
openCommerceAction()resolves an external checkout only after the API validates the organization, plan, catalogue publication, offering availability, and action.useStreamingChat()now exposes bothcommerceandresourcesfrom the completed response.
What's New In 0.5.0
- Structured resources are available on chat, streaming, and voice responses.
- Supported resource kinds:
VIDEO,AUDIO,STORE,REDIRECT,REFERRAL, andCHECKOUT. - Video and audio resources can include a safe
embedUrlfor inline rendering. useStreamingChat()now exposes the completed response'sresources.
Install
npm install @fluxyte/sdkRequirements
- Browser or Node.js 18+ (global
fetchavailable) - A Fluxyte API key (sent as
X-API-Key)pk_*for browser/public SDK usagesk_*for backend/server usage only
Authentication (API Key)
Treat your API key like a password. Do not commit it to source control.
Create an API key
- Sign up at
https://fluxyte.com/signup - Verify your email
- Open the
Accountmenu - Select
API Keys - Click
Create API Key - Choose key type:
pk_*(PUBLIC) for frontend/browser SDK usagesk_*(SECRET) for backend/server-only usage
- Copy your API key (shown once)
Use an API key
All integrations authenticate with an API key sent in the X-API-Key header.
- Use
pk_*keys in browser/public SDK integrations - Use
sk_*keys only in backend/server environments - For
pk_*keys, configure allowed origins to restrict frontend domains - The key controls organization access, docs scope, and analytics ownership
Environment examples
- Vite:
VITE_FLUXYTE_API_KEY=pk_... - Next.js:
NEXT_PUBLIC_FLUXYTE_API_KEY=pk_...(public key only) - Server:
FLUXYTE_API_KEY=sk_...
The SDK rejects sk_* keys in browser environments to prevent accidental exposure.
Key Management
Key Purpose
pk_*(PUBLIC): for browser/frontend SDK usage.sk_*(SECRET): for backend/server usage only.
How to get keys
- Sign in to Fluxyte dashboard.
- Go to
Account->API Keys. - Create a key and choose type:
PUBLIC (pk_*)for frontend SDK traffic.SECRET (sk_*)for backend automation or server integrations.
- Copy the key immediately (shown once).
Allowed origins (PUBLIC keys)
For pk_* keys, configure allowed origins in dashboard (for example https://app.example.com).
This limits where browser-based SDK requests are accepted from.
Rotation and revocation
- Rotate keys on a regular schedule (recommended every 60-90 days).
- Keep a short overlap window where old and new keys are both valid during rollout.
- Revoke keys immediately if exposed.
- Update environment variables and redeploy clients after rotation.
Environment examples
- Frontend:
NEXT_PUBLIC_FLUXYTE_API_KEY=pk_... - Backend:
FLUXYTE_API_KEY=sk_...
Never expose sk_* in browser bundles, client logs, or public repos.
Choose An Entrypoint
The SDK ships multiple entrypoints, all with the same API surface:
@fluxyte/sdk/react(React hooks + provider)@fluxyte/sdk/node(server-side; validatesfetchavailability)@fluxyte/sdk/vanilla(browser usage without React)@fluxyte/sdk(base exports)
Create A Client (Node / Vanilla)
import { OnboardingAIClient } from "@fluxyte/sdk/node";
const client = new OnboardingAIClient(process.env.FLUXYTE_API_KEY!);Client Options (Session Handling)
The SDK enforces stable identity. Chat and voice accept top-level sessionId or
userId; onboarding events retain identity inside their event context.
- By default, it auto-generates and reuses
sessionIdwhen missing. - You can disable this with
autoSessionId: false.
const client = new OnboardingAIClient(process.env.FLUXYTE_API_KEY!, {
autoSessionId: true, // default
sessionStorageKey: "fluxyte_onboarding_session_id", // browser storage key
});Chat Completions (Non-Streaming)
const res = await client.chat({
message: "How do I connect my database?",
sessionId: "sess_123",
context: {
stepSlug: "connect_database",
pageUrl: "https://app.example.com/setup/database",
},
});
console.log(res.answerId);
console.log(res.reply);
console.log(res.confidence);
console.log(res.sources);
console.log(res.resources);
console.log(res.commerce);Product Catalogue and Commerce
When an organization has published catalogue items and its plan includes Commerce, chat responses may include a structured presentation alongside the natural-language reply:
for (const offering of res.commerce?.offerings ?? []) {
console.log(offering.name);
console.log(offering.priceAmountMinor, offering.currency);
console.log(offering.availability);
console.log(offering.features);
console.log(offering.actions);
}
if (res.commerce?.hasMore) {
// Send a normal semantic continuation, such as "Show me more".
}The API returns at most five offerings for catalogue discovery at a time. Do not implement client-side slicing or infer the next page; send the user's semantic continuation so the server can advance durable Commerce state.
Catalogue actions are typed as:
EXTERNAL_CHECKOUT— resolve throughopenCommerceAction().REQUEST_QUOTE— send the action label/intention through chat.CONTACT_SALES— send the action label/intention through chat.
Only external checkout is a redirect. Never construct or cache checkout URLs from catalogue data. Resolve the selected action immediately before navigation:
const action = offering.actions.find(
(candidate) => candidate.kind === "EXTERNAL_CHECKOUT",
);
if (action) {
const redirect = await client.openCommerceAction(action.id, "sess_123");
if (redirect.kind === "REDIRECT") {
window.location.assign(redirect.url);
}
}Rich Content Resources
When approved knowledge or a flow step includes a related resource, the response can contain:
type ContentResource = {
id: string;
kind: "VIDEO" | "AUDIO" | "STORE" | "REDIRECT" | "REFERRAL" | "CHECKOUT";
url: string;
label: string;
embedUrl?: string | null;
};Use url for links and actions. Use embedUrl only when it is present; it is
the server-approved URL intended for an embedded video or audio player.
for (const resource of res.resources ?? []) {
if (resource.embedUrl) {
renderEmbeddedMedia(resource.embedUrl, resource.label);
} else {
renderResourceLink(resource.url, resource.label);
}
}Chat Completions (Streaming via SSE)
Streaming is useful when you want:
- live typing UX
- progressive rendering
- early access to
answerId(for feedback)
Streaming lifecycle:
meta(containsanswerId)delta(partial text; one or more)done(confidence, sources, resources, commerce)
const stop = client.streamChat(
{
message: "What's the next step?",
sessionId: "sess_123",
context: { stepSlug: "connect_database" },
},
(event) => {
if (event.type === "meta") console.log("Answer ID:", event.answerId);
if (event.type === "delta") process.stdout.write(event.replyDelta);
if (event.type === "done") {
console.log("\nConfidence:", event.confidence);
console.log("Sources:", event.sources);
console.log("Resources:", event.resources);
console.log("Commerce:", event.commerce);
}
},
(err) => {
// Optional: handle auth/network/server errors.
console.error("Streaming error:", err);
},
);
// stop() cancels streamingVoice Chat (Speech In + Optional Speech Out)
const voice = await client.voiceChat({
audioBase64: "BASE64_AUDIO",
mimeType: "audio/webm",
userId: "user_123",
context: { stepSlug: "connect_database", locale: "en-NG" },
synthesize: true,
voice: "alloy",
audioFormat: "mp3",
});
console.log(voice.transcript); // text recognized from audio
console.log(voice.reply); // AI text reply
console.log(voice.replyAudioBase64); // optional synthesized voice
console.log(voice.resources); // approved related links or embedded mediaContext
Context is optional for chat and voice requests. Identity is separate and required;
the SDK auto-generates a reusable sessionId unless autoSessionId is disabled.
type PublicChatContext = {
catalogueSubjectId?: string;
stepSlug?: string;
endpoint?: string;
pageUrl?: string;
error?: {
code?: string;
description?: string;
field?: string;
source?: "client" | "server" | "network" | "third_party";
httpStatus?: number;
retryable?: boolean;
};
attemptedAction?: {
name: string;
description?: string;
target?: string;
status?: "started" | "blocked" | "failed" | "completed";
};
sdk?: "react" | "node" | "vanilla" | "rest";
sdkVersion?: string;
appVersion?: string;
environment?: "development" | "staging" | "production";
locale?: string;
timezone?: string;
};Best practices:
- Pass
catalogueSubjectIdwhen the customer is viewing a published product or service. - Pass
stepSlugwhen the customer is inside a published onboarding step. - Keep
sessionIdanduserIdat the request's top level, outside context. - Treat context like application state (update it as the user moves)
- For task assistance or troubleshooting, pass non-secret diagnostic context when known
Identity guidance:
- Anonymous visitors: let SDK auto-manage
sessionIdor pass your own persisted ID. - Logged-in users: pass a stable top-level
userId.
Localization & Timezone
Pass optional localization and timezone fields so the API can tailor user-facing formatting and time-aware utility responses:
context: {
locale: "en-US", // browser/client locale for user-facing formatting
timezone: "Africa/Lagos", // IANA timezone for the current user
}locale— browser/client locale (for exampleen-US,en-NG) used for user-facing formatting.timezone— IANA timezone for the current user (for exampleAmerica/New_York,Africa/Lagos,Europe/London).
Task and troubleshooting context
The public assistant can use structured context to understand the user's current task and troubleshoot with fewer clarification turns. Pass only non-secret values:
await client.chat({
message: "I get a 401 when I send my first message",
userId: "user_123",
context: {
sdk: "react",
sdkVersion: "0.8.0",
appVersion: "2026.08.30",
environment: "production",
endpoint: "/v1/chat/completions",
pageUrl: "https://app.example.com/setup/chat",
error: {
code: "AUTHENTICATION_FAILED",
description: "The first chat request returned 401 after the user saved their public API key.",
source: "server",
httpStatus: 401,
retryable: false,
},
attemptedAction: {
name: "send_first_chat_message",
description: "Send the first message from the React setup screen.",
target: "Public AI chat",
status: "failed",
},
},
});sdkidentifies the client or entrypoint in use.sdkVersionidentifies the Fluxyte SDK version andappVersionthe integrating app.environmentisdevelopment,staging, orproduction.endpointidentifies the affected API route or operation.errorcarries structured, customer-safe diagnostics, including a comprehensive description.attemptedActiondescribes the action, target, and outcome without duplicating the user's message.
Do not put API keys, access tokens, passwords, request bodies containing personal data, or other secrets in context.
Onboarding Events
Events power onboarding analytics, drop-off detection, and AI insights.
Supported event types:
FLOW_STARTED
- User begins a tracked onboarding flow.
- Send once when the flow is entered.
STEP_VIEWED
- User lands on or opens a specific step.
- Send whenever the current step changes.
STEP_COMPLETED
- User successfully completes a step.
- Send only after verified completion signal.
FLOW_COMPLETED
- User completes all required steps in the flow.
- Send once at successful finish.
ABANDONED
- User exits/stalls before completion.
- Send when inactivity timeout or explicit exit indicates drop-off.
Recommended minimum context for event quality:
flowIdstepId(for step-level events)- stable identity (
context.sessionIdorcontext.userId)
Typical event sequence:
FLOW_STARTEDSTEP_VIEWED(step 1)STEP_COMPLETED(step 1)STEP_VIEWED(step 2)STEP_COMPLETED(step 2)FLOW_COMPLETED
Drop-off sequence example:
FLOW_STARTEDSTEP_VIEWED(step 1)STEP_VIEWED(step 2)ABANDONED
await client.sendEvent({
type: "STEP_COMPLETED",
context: {
flowId: "premium-support-setup",
stepId: "connect-database",
userId: "customer_123",
},
});Feedback
await client.submitFeedback({
answerId: "ans_7xk9p2m",
rating: "GOOD",
comment: "Clear explanation and actionable advice",
});React Usage (Recommended)
import { OnboardingAIClient } from "@fluxyte/sdk";
import { OnboardingAIProvider } from "@fluxyte/sdk/react";
const client = new OnboardingAIClient(import.meta.env.VITE_FLUXYTE_API_KEY);
export function App() {
return (
<OnboardingAIProvider client={client}>
{/* your app */}
</OnboardingAIProvider>
);
}React Hooks
import { useChat } from "@fluxyte/sdk/react";
const { send, data, loading, error } = useChat();
await send({
message: "How do I connect my database?",
sessionId: "sess_123",
context: { stepSlug: "connect_database" },
});import { useStreamingChat } from "@fluxyte/sdk/react";
const { text, answerId, confidence, resources, commerce, streaming, start, stop } =
useStreamingChat();
start({
message: "What's the next step?",
context: { stepSlug: "connect_database" },
});import { useVoiceChat } from "@fluxyte/sdk/react";
const { sendVoice, loading, data, error } = useVoiceChat();
const res = await sendVoice({
audioBase64: "BASE64_AUDIO",
mimeType: "audio/webm",
context: { stepSlug: "connect_database" },
synthesize: true,
voice: "alloy",
audioFormat: "mp3",
});
console.log(res.transcript);
console.log(res.reply);Multi-Target
Use context.product or context.service to isolate onboarding targets under one account (apps, APIs, and services).
Error Handling
import { APIError } from "@fluxyte/sdk";
try {
await client.chat(/* ... */);
} catch (err) {
if (err instanceof APIError) {
console.error(err.status, err.message);
}
}License
Commercial. See LICENSE.md.
