[V2] BYO (Bring Your Own) Auth + Chat
Designed for products with their own backend and authentication, this version gives you full control over user onboarding, syncing, and logout while seamlessly integrating powerful Sageion capabilities.
Prerequisite
- Sign up / log in to your Sageion account.
- Create a New App and select Version V2 during setup.
- Enable at least one of the three AI bots â FAQ/QNA Tree, AI Chat, or Live Agent. An app cannot be created without one.
- Open the App Details page and note your: App Name, API Key, and Region (US or IN).
You can change these later
Bots, settings, and theme are all editable from the App Details page after creation. Pick whatever makes sense to start with.
Project setup
Client Side Integration
Sageion exposes two methods on window.sageion_os: setUp() and initialize(). Everything else â sockets, DOM, auth lifecycle, teardown â is handled internally. This page documents the two methods and how to call them correctly.
The API in one sentence
Call setUp() once per page load. Call initialize({ uid }) whenever the current user changes â logged in, logged out, or switched. That's the entire contract.
The four rules of a correct integration
- setUp() runs once, awaited, before any initialize().
- initialize() is called from exactly one place in your app.
- initialize() is gated on your auth state having settled â not on the user being non-null.
- initialize() receives the current user, once per change.
Follow these four rules and Sageion handles every transition â login, logout, user-switch, token refresh â without a page reload. The SDK is idempotent: calling initialize() twice with the same payload is a safe no-op, so you never need to add re-render guards.
Lifecycle at a glance
- Load the Socket.IO and Sageion bundle <script> tags once, in your app's HTML shell. Order matters: Socket.IO first, Sageion bundle second.
- Call setUp() once â after the scripts load, before anything else. Await it.
- Call initialize({ uid }) for a logged-in user, or initialize({}) for anonymous. Do this once your auth layer has settled.
- When the user logs in, logs out, or switches, call initialize() again with the new payload. No page reload, no second setUp().
setUp()
setUp() is configuration. It loads app data from the server, verifies your API key, and prepares the SDK. It runs once per page load.
await window.sageion_os.setUp(
"your_app_id", // the app_id shown in your Sageion dashboard
"YOUR_API_KEY", // the auth_key shown in your Sageion dashboard
"US", // region: "US" or "IN"
"sageion-chat-root" // optional: id of a DOM element to mount into
);Call setUp() exactly once per page load
- It is not a per-route or per-navigation call. Client-side route changes do not need it to re-run.
- After login or logout, do NOT call setUp() again. Use initialize() instead.
- The only case where setUp() runs again is a full browser reload.
The fourth argument is optional
When chat_root_id is omitted, the widget floats in the bottom-right corner of the page. When provided, it mounts inside the element with that id.
If your app is still in draft mode
If the app has not been published yet in your Sageion dashboard, setUp() completes without error but deliberately does not mount the widget. Any subsequent initialize() call becomes a no-op. This is intentional â a half-configured app should not ship a half-working widget. Publish the app from the dashboard, then reload.
initialize()
initialize() tells the SDK who the current user is, and the SDK reflects that in the widget. It handles every auth transition â login, logout, and user-switch â without a page reload. Calling it with the same payload twice is a safe no-op, so it does not matter how often your framework re-runs the effect that calls it.
// User is logged in
await window.sageion_os.initialize({ uid: "42" });
// User is anonymous, or just logged out
await window.sageion_os.initialize({});One method handles every auth transition
| Current state | Call | What happens |
|---|---|---|
| Anonymous visitor | initialize({ uid: "Alice's id" }) | Chat opens as Alice. |
| Logged in as Alice | initialize({}) | Alice is logged out; chat stays mounted as anonymous. |
| Logged in as Alice | initialize({ uid: "Alice's id" }) | Safe no-op â nothing changes. |
| Logged in as Alice | initialize({ uid: "Bob's id" }) | Chat switches to Bob. |
| Anonymous visitor | initialize({}) | Safe no-op. |
There is no separate logout call. To log a user out, call initialize({}). The SDK handles the transition.
You do not need to skip initialize() when no one is logged in. Calling it with {} is correct and safe â the widget stays mounted in anonymous mode.
Call initialize() from exactly one place
- Don't call it speculatively â for example with {} "to start" and then with { uid } a moment later. That produces an unnecessary anonymousâauthenticated transition on every page load.
- Wait until your auth layer has finished resolving before calling. If your auth state has a loading flag, gate on loading === false.
- If two different effects in your app both call initialize(), they will race with different payloads. Consolidate into a single effect that watches the current user.
1. Load the scripts
Locate your app's root HTML shell (usually index.html, app.html, or a base layout template) and insert the following scripts. Socket.IO must load before the Sageion bundle.
<script src="https://cdn.socket.io/4.1.2/socket.io.min.js"></script>
<script src="https://magicchat-core.github.io/prod-ssc-client-cdns/bundle.js"></script>The SDK is a global, not an npm package
Loading the bundle exposes window.sageion_os. Every example below uses that global. There is no npm install, no import statement, and no build-time integration.
Optional: custom mount point
By default, the chat bubble floats in the bottom-right corner of the page. To anchor it inside a specific container, add an empty element to your markup and pass its id as the fourth argument to setUp():
<div id="sageion-chat-root"></div>2. Pick your framework
Pick your framework from the tabs below. Inside each you will find three integration styles â choose the one that matches your app's structure. All three are valid; they differ only in how the two calls are split across files.
What changes between frameworks
The four rules are the same everywhere. The only thing that changes between frameworks is how you express "an effect that watches auth state" â useEffect in React, watch in Vue, $: in Svelte, and so on.
Plain HTML and JavaScript. This tab also covers jQuery, Alpine.js, HTMX, and Stimulus â the SDK treats them identically.
Single-Block â Vanilla JS
Both calls awaited in order, inside a single <script> tag.
<script>
(async () => {
try {
await window.sageion_os.setUp(
"your_app_id",
"YOUR_API_KEY",
"US"
);
const token = localStorage.getItem("token");
let payload = {};
if (token) {
const res = await fetch("https://api.yourbackend.com/auth/profile", {
headers: { Authorization: `Bearer ${token}` }
});
if (res.ok) {
const user = await res.json();
payload = { uid: user.id.toString() };
} else {
localStorage.removeItem("token");
}
}
await window.sageion_os.initialize(payload);
} catch (err) {
console.error("[Sageion] bootstrap failed:", err);
}
})();
</script>Reflecting login & logout at runtime
The block above bootstraps the SDK once on page load. To handle a user logging in, logging out, or switching accounts without a page reload, call initialize() again from wherever your app already reacts to auth changes â a click handler, a store subscriber, a router hook. The rule is the same: one call site, gated on auth having settled.
// wherever your app knows the user changed:
function onAuthChanged(user, loading) {
if (loading) return; // wait for auth to settle
window.sageion_os
.initialize(user ? { uid: String(user.id) } : {})
.catch(err => console.error("[Sageion] sync failed:", err));
}Frameworks not listed
Sageion attaches to window and never touches your framework's rendering. If your framework is not in the tabs above, pick whichever of these is closest â the client-side code is framework-agnostic.
Common unlisted frameworks
- Solid, Preact, Lit â use the React or Vanilla JS pattern.
- Phoenix (Elixir) â use the Django or Rails pattern.
- Hugo, Jekyll, Eleventy â static site generators; use the Vanilla JS pattern and place scripts in your base layout.
- Gatsby â use the React pattern; add the scripts to gatsby-ssr.js.
- Ember â use the Vanilla JS pattern; add the scripts to app/index.html.
Common mistakes
If something looks wrong, first open your browser console â the SDK logs a step-by-step trace you can follow. These are the most frequent issues users hit during integration:
| What you see | Likely cause | Fix |
|---|---|---|
| An error popup appears immediately when the page loads, mentioning api_key or app_id. | The api_key or app_id you passed to setUp() does not match this app. | Double-check both values against your app's settings, then click Reset Settings in the popup and reload. |
| An error popup mentions that the current domain is not authorized. | Your hostname is not in this app's allowed domains. | Ask your Sageion admin to add the domain, then reload. |
| An error popup mentions that initialize ran before setUp could finish. | initialize() was called from a separate DOMContentLoaded listener, or from two separate scripts that both awaited the page load. | Use the Single-Block or Two-Block pattern. If you must split, bridge with a shared promise as shown. |
| The chat bubble never appears. | setUp() or initialize() threw an error and the widget was never mounted, or the scripts never loaded. | Check the console for errors. Confirm both script tags are present in your HTML shell and appear in the correct order. |
| The chat bubble appears, but clicking it does nothing. | A script error occurred while mounting the widget, or the SDK global is not defined on window. | Confirm the Sageion bundle loaded after Socket.IO, and that no other script on the page overwrote window.sageion_os. |
| After login or logout, the chat still shows the previous user. | The SDK was not notified of the auth change. | Call initialize({ uid } | {}) whenever your auth state changes â a single effect watching your auth store covers every case. |
| After login or logout, the whole page reloads. | You are using a framework-native redirect instead of calling initialize(). | Replace the redirect with an initialize() call. The SDK handles the transition without a reload. |
| The widget briefly shows the anonymous view, then flickers to the authenticated view on page load. | initialize() was called twice â once with {} before auth resolved, once with { uid } after. | Gate initialize() on your auth layer's loading === false state. Only call it once the current user is known. |
| initialize runs with different payloads from two places in your app. | Two or more effects or scripts are calling initialize(). | Consolidate into a single effect that watches the current user. Rule 2 of the four rules. |
Example implementations
Complete working examples on GitHub:
Connecting Sageion to Your Product's Authentication
Sageion does not own your user identities. Your product remains the source of truth â users sign up and log in against your own backend, and Sageion is told about them via a small onboarding call. This page shows the full flow end-to-end.
đ How identity flows
- A user signs up in your app. Your backend creates the user record and returns its own token.
- Your backend calls Sageion's onboarding endpoint with the user's uid and your app_id. This maps the user into Sageion.
- On the frontend, your app calls initialize({ uid }) with the same uid. Sageion now knows which of its users this is.
- When the user logs out, your app calls initialize({}) so Sageion clears the session. No page reload needed.
UID is the only link
The uid you pass to onboarding must match the uid you pass to initialize() exactly. Sageion has no other way to know which of your users is which. Use your own users.id, users.uid, or another stable unique key â just be consistent, and always send it as a string.
Onboarding API
The onboarding endpoint registers a user with Sageion so they can appear in the Admin Panel and use the chat box.
POST https://{region}.userauth2.sageion.com/prod/onboardingReplace {region} with your Sageion region â either us or in. It's the same value you pass as region to setUp() on the frontend.
Headers
| Header | Value | Where to get it |
|---|---|---|
| X-API-Key | Your Sageion REST API key | Sageion Admin Panel â App Details â REST API Key |
| Content-Type | application/json | Always this value |
Body
| Field | Type | Required | Description |
|---|---|---|---|
| uid | string | Yes | Your platform's unique user identifier, as a string. Must match what you pass to initialize() on the frontend. |
| app_id | string | Yes | Your Sageion application id, from App Details in the Admin Panel. This is the same value you pass as the first argument to setUp() on the frontend. |
| metadata | object | No | Optional display information about the user. Currently supported keys are full_name (string) and image (string URL). If omitted, the user is onboarded with no display name or avatar. |
What metadata is for
The metadata object is what shows up in the Sageion Admin Panel next to the user's uid â their display name and avatar. It's cosmetic: the chat box works without it, but agents see a more useful user list when it's present.
Only full_name and image are read today. Any other keys you send are stored but currently unused, so don't rely on them yet.
Example request
curl --location 'https://us.userauth2.sageion.com/prod/onboarding' \
--header 'X-API-Key: YOUR_REST_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"uid": "12345",
"app_id": "your_application_id",
"metadata": {
"full_name": "Jane Doe",
"image": "https://example.com/avatars/jane.jpg"
}
}'Response
A successful onboarding returns HTTP 200 with a small confirmation payload. Once onboarded, the user appears under Users in the Sageion Admin Panel for that app.
Response contract â status codes only
The onboarding response body is not read by Sageion. What matters is the status code: 2xx means the user is onboarded. If the user was already onboarded, your handler should still return 2xx â onboarding is idempotent. On failure, return 4xx or 5xx so your own retry logic can detect it. Because the client SDK treats any 2xx as success, do not return 200 on failure.
Where to call onboarding
Onboarding must be called exactly once per user, ideally the moment your own signup succeeds. Pick your backend language below, then choose the onboarding method that matches your workflow.
Express + axios. This is the reference implementation used by Sageion's own sample app.
Backend onboarding (Node.js)
Call onboarding inside your /register handler, right after your own user row is created. It's fire-and-forget: your signup succeeds even if onboarding fails.
// routes/auth.js
const axios = require('axios');
router.post('/register', [...validators], async (req, res) => {
const { email, password, full_name } = req.body;
// 1. Create the user in your own DB
const hashed = await hashPassword(password);
const result = await pool.query(
'INSERT INTO users (email, password_hash, full_name) VALUES ($1, $2, $3) RETURNING id, email, full_name, role',
[email, hashed, full_name]
);
const user = result.rows[0];
// 2. Onboard the user into Sageion (fire-and-forget)
try {
const onboardingUrl = `https://${process.env.SAGEION_REGION}.userauth2.sageion.com/prod/onboarding`;
await axios.post(
onboardingUrl,
{
uid: user.id.toString(),
app_id: process.env.SAGEION_APP_ID,
metadata: {
full_name: user.full_name,
image: "https://img.magnific.com/free-vector/blue-circle-with-white-user_78370-4707.jpg",
},
},
{
headers: {
'X-API-Key': process.env.SAGEION_REST_API_KEY,
'Content-Type': 'application/json',
},
timeout: 5000,
}
);
} catch (onboardErr) {
// Do NOT fail registration â the user can still log in and use your app.
// The chat box just won't work for this user until they're onboarded.
console.error('Sageion onboarding error:', onboardErr.message);
}
// 3. Return your own token â Sageion does not issue auth tokens
const token = generateToken(user.id, user.email, user.role);
res.status(201).json({ token, user });
});Onboarding failure is silent by design
If the onboarding call fails, registration still succeeds. Your user exists in your DB but not in Sageion â the chat box won't work for them until they're onboarded. Add an alert or a background retry so you notice.
What onboarded users look like
Once a user is onboarded, they appear in the Sageion Admin Panel under your application, ready for chat. Applications without any onboarded users show an empty state.
1
Admin Panel â users present

2
Admin Panel â no users yet

APIs the AI agent can call â sync vs. async
Every API you register with Sageion falls into one of two categories, depending on how quickly it can produce its final result. Pick the one that matches the nature of the endpoint â most APIs are synchronous, and you only reach for async when the final result genuinely cannot be produced within the request lifecycle.
| Synchronous (default) | Asynchronous (Async Callback enabled) | |
|---|---|---|
| When to use | The endpoint can compute and return the final result within a few seconds of the request. | The endpoint cannot produce the final result immediately â it depends on a payment gateway, an approval, a background job, or an external event. |
| How the agent gets the result | Reads it from the HTTP response body. | Waits for your backend to POST the final result to Sageion's webhook callback URL. |
| What your handler does | Does the work, returns the final result. | Acknowledges the request, kicks off the work, returns early â then POSTs the final result via webhook when it's ready. |
| What Sageion sends | Nothing extra. | An x-correlation-id header on the initial request. |
| Where the config lives | Nothing to configure â this is the default. | Enable Async Callback when registering the API in the Sageion Admin Panel. |
One endpoint, one nature
An endpoint is either synchronous or asynchronous â it does not switch between the two at runtime. The example code below uses an if (correlation_id) branch purely to illustrate both paths on one screen; a real integration picks one and sticks with it. If your API is synchronous, you never read x-correlation-id. If it's asynchronous, Sageion always sends it (because you enabled Async Callback for that API) and your handler always uses it.
Path A â Synchronous API
You write your handler exactly as you would for any normal API. Sageion calls your endpoint, waits for the response, and uses the body as the final result. No special headers to read, no webhook to post â nothing.
// Example: a bookings endpoint that confirms the reservation inline.
// This is what a synchronous API looks like â no correlation_id, no webhook.
router.post('/bookings', [...validators], async (req, res) => {
const { room_id, check_in, check_out } = req.body;
const user_id = req.user.userId;
// Do the work and return the final result. That's it.
const booking = await createBooking(user_id, room_id, check_in, check_out);
res.status(201).json({
success: true,
booking_id: booking.id,
status: booking.status,
});
});You're done
If your API is synchronous, that's all you need to know. Everything that follows in this section is for the async case only.
Path B â Asynchronous API (Async Callback enabled)
You register the API in the Sageion Admin Panel with Async Callback enabled. From then on, Sageion attaches an x-correlation-id header to every request to that endpoint and treats your initial response as an acknowledgment, not as the final answer.
đ When async is the right choice
- The action depends on a payment gateway â the user pays, then the gateway confirms minutes later.
- The action depends on a human approval that happens out-of-band (a manager clicks approve).
- The action kicks off a multi-step workflow in your own system whose completion is signalled by a separate event.
- The action needs to send the user an email or SMS and wait for a response before it can produce a final result.
If none of these apply â if your backend can compute the final result by the time the request handler returns â use the synchronous path instead. Async adds complexity, and there's no reason to reach for it prematurely.
How the async flow works
1
Sageion sends the request with x-correlation-id
Because the API is configured with Async Callback enabled, Sageion attaches an x-correlation-id header to every call. This header is the only thing that distinguishes an async-configured call from a synchronous one.
2
Your handler acknowledges the request and kicks off the work
Read req.headers['x-correlation-id'], start whatever needs to happen (send a payment link, queue a job, notify another service), and respond immediately â usually with HTTP 202 and any interim data the user should see. Do not wait for the async work to complete inside the handler.
3
Later â when the work completes â your backend POSTs to Sageion's webhook
Once the async operation finishes (payment confirmed, job complete, external system replied), your backend â or the external service's own webhook handler in your code â POSTs a JSON body containing the same correlation_id and the final data to Sageion's webhook callback URL.
4
Sageion matches the correlation_id and resumes the workflow
The workflow engine pairs the callback with the original request, resumes execution, and passes the data you sent into the next step.
Request header: x-correlation-id
| Header | Type | Description |
|---|---|---|
| x-correlation-id | string | Sent by Sageion on every request to an API configured with Async Callback. Your handler reads it and echoes it back in the webhook payload so the callback can be matched to the original request. |
Webhook callback contract
POST https://{region}.autobot2.sageion.com/prod/webhook/callbackThis is Sageion's webhook receiver. Your backend posts here when the async operation completes. The URL and environment suffix vary by region â use the one configured in your Admin Panel's webhook settings.
| Field | Type | Required | Description |
|---|---|---|---|
| correlation_id | string | Yes | The exact x-correlation-id value Sageion sent in the original request. Used to match the callback to the workflow step. |
| data | object | Yes | The final payload the workflow engine should receive as the API response. Any JSON shape is allowed â Sageion passes it through to the next step. |
Response format is a contract â match it exactly
- correlation_id must be the verbatim string from the request header. Do not reformat, prefix, or wrap it.
- data must be a top-level object, not a string. Wrapping the payload in JSON.stringify() before posting will break parsing.
- The webhook POST should return 2xx. Sageion retries on non-2xx responses, so return 200 immediately after your handler acknowledges the callback â do not delay on downstream work.
- Extra top-level fields beyond correlation_id and data are ignored.
Worked example â a booking that waits on payment
Consider a hotel booking API. When the user asks to book a room, the API does not confirm the booking immediately â instead, it emails a payment link. The booking only becomes confirmed once the payment gateway reports success, which happens minutes later. This is the textbook case for async: the final result genuinely cannot be produced within the request lifecycle.
Below are the same booking endpoint written both ways, so you can see exactly where the async pattern diverges. The synchronous version confirms the booking inline and returns. The async version acknowledges the request, sends the payment link, and produces the final result later via the payment provider's webhook handler.
The endpoint does everything up front and returns the confirmed booking. Sageion reads the result from the HTTP response body. No x-correlation-id is present, no webhook is involved.
// routes/bookings.js â SYNC booking (confirms immediately)
router.post('/', [...validators], async (req, res) => {
const { room_id, check_in, check_out } = req.body;
const user_id = req.user.userId;
// Do all the work now and return the final result.
const booking = await createBooking(user_id, room_id, check_in, check_out);
res.status(201).json({
success: true,
booking_id: booking.id,
status: 'confirmed',
});
});Async handler â reference implementations
The concept is identical across languages: read x-correlation-id, return early, then POST the final result to Sageion's webhook callback when the async work finishes. Below are minimal reference implementations.
// routes/orders.js â async order submission
const axios = require('axios');
router.post('/orders', async (req, res) => {
const correlation_id = req.headers['x-correlation-id'];
// Kick off the long-running work (queue a job, call an external system).
const order = await createPendingOrder(req.body);
await attachCorrelationId(order.id, correlation_id);
// Return early.
res.status(202).json({ success: true, order_id: order.id, status: 'processing' });
// ... elsewhere, when the work finishes:
// await axios.post(
// `https://${process.env.SAGEION_REGION}.autobot2.sageion.com/prod/webhook/callback`,
// {
// correlation_id,
// data: { success: true, order_id: order.id, status: 'completed' },
// }
// );
});â Checklist for async APIs
- Enable Async Callback in the Sageion Admin Panel when you register the API. Without this, Sageion sends no x-correlation-id and your handler will not know a webhook is expected.
- Read x-correlation-id at the very top of the handler, before any branch that could return early.
- Persist the correlation_id alongside the entity the async work is about (order, booking, job). You will need it in a completely different request later.
- Respond to the initial request quickly â 2xx with any interim data. Do not wait for the async work inside the original handler.
- When the async work finishes, POST to Sageion's webhook callback with the same correlation_id, verbatim, and a data object containing the final result.
- Log the correlation_id at every step of your pipeline. It is the only way to correlate Sageion's original request with your eventual callback.
Environment variables
Your backend needs these variables. Add them to your server's environment â never expose SAGEION_REST_API_KEY, SAGEION_CLIENT_SECRET, or SAGEION_PUBLIC_KEY_PEM to the browser.
| Variable | Example | Used for |
|---|---|---|
| SAGEION_REGION | us | Regional prefix in the onboarding URL and webhook callback URL. |
| SAGEION_APP_ID | your_application_id | Your Sageion app id. Sent as app_id in onboarding requests. |
| SAGEION_REST_API_KEY | your_rest_api_key | X-API-Key header for onboarding. |
| SAGEION_CLIENT_SECRET | your_client_secret | Verifies client credentials on /client-user-token (only needed if you enable the optional AI agent section below). Never expose to the browser. |
| SAGEION_PUBLIC_KEY_PATH | /etc/sageion/sageion-public.pem | Path to the PEM file containing the public key from the Token Encryption Key section. Used to encrypt tokens returned from /client-user-token. Recommended over the inline PEM for production. |
| SAGEION_PUBLIC_KEY_PEM | -----BEGIN PUBLIC KEY-----\nMIIBIjANBg... | Inline PEM alternative to SAGEION_PUBLIC_KEY_PATH. Useful in environments where mounting a file is inconvenient (single-file deploys, some serverless runtimes). When both are set, the path takes precedence. |
| WEBHOOK_CALLBACK_URL | https://us.autobot2.sageion.com/prod/webhook/callback | Where your backend posts async results for APIs configured with webhook enabled. |
â ī¸ The encryption key is required for /client-user-token
If your backend exposes /client-user-token (the optional AI agent section), it must encrypt the token it returns using the public key from Token Encryption Key. Set either SAGEION_PUBLIC_KEY_PATH or SAGEION_PUBLIC_KEY_PEM â the server should refuse to start without one of them so you find out at deploy time instead of at runtime.
đĄ Which one should I use?
- SAGEION_PUBLIC_KEY_PATH â Recommended for production. Put the PEM in a file, point the variable at it, and mount the file into your container or server. Keeps the key out of environment listings and logs.
- SAGEION_PUBLIC_KEY_PEM â Fallback for environments where file mounts aren't practical. Note that inline PEMs in environment variables sometimes get line-ending mangled â replace literal newlines with the two-character sequence \n and let your code translate them back.
â Base integration checklist
- Trigger onboarding immediately after your own user is created â inside the same signup handler, not in a background job.
- Treat onboarding failures as non-fatal to signup, but log them and add an alert so you notice missing users.
- Use the exact same uid in onboarding and in initialize({ uid }) â they must match for the chat box to work. Always send it as a string.
- When the user logs out, call initialize({}) from your own logout handler, before clearing your own session.
- Never ship SAGEION_CLIENT_SECRET, SAGEION_REST_API_KEY, or SAGEION_PUBLIC_KEY_PEM to the frontend. If you use the frontend onboarding method, use a different token scoped to onboarding only.
- For bulk onboarding of existing users, contact Sageion Support before calling the API in a loop.
Once all six items above are done, your Sageion integration is complete. The next section is optional and can be added at any time.
Binding the AI agent to a user for authenticated API access (Optional)
đ Optional â add this whenever you need it
You do not need this section to get Sageion's chat box running. Your users can chat with the AI agent without it. Set it up only when you want the AI agent to access protected endpoints on your own backend â for example, to fetch or modify a specific user's bookings on their behalf.
You can do this during your initial integration from day one, or add it later when the need arises â nothing on this page conflicts with anything above.
â ī¸ Response format is a contract â match it exactly
For the AI agent to successfully call your /auth/client-user-token, /auth/send-otp, and /auth/verify-otp endpoints, your handlers must return responses in the exact shape documented below. The workflow engine reads specific field names from each response â it does not adapt to renames, extra wrappers, or missing fields.
- Do not wrap responses in { data: { ... } } or { result: { ... } } â return the fields at the top level.
- Do not rename fields. token must be token, user_id must be user_id, scope must be scope, expires_in must be expires_in.
- Do not omit fields. expires_in and scope are read by the client to decide token freshness and permitted actions.
- Extra fields beyond the ones documented are allowed and will be ignored.
- Status codes matter: 200 for success, 401 for invalid client credentials, 404 for unknown user. The workflow engine branches on these codes.
What problem does this solve?
By default, the AI agent talks to your backend as a generic client. If your backend exposes user-scoped endpoints (like GET /bookings/me), the agent has no way to prove who it's acting for â so it can't reach those endpoints.
This integration closes that gap. Your backend exchanges its client credentials for a short-lived, scoped token tied to a specific user. The agent then calls your authenticated endpoints as that user.
đ§Š When you need this
- Your AI workflows call your own backend APIs on behalf of a logged-in user
- You want fine-grained scopes (read, create, update, cancel) rather than blanket access
- You want short-lived tokens (1 hour) rather than long-lived user sessions
1. Agent token endpoint (/auth/client-user-token)
Your backend exposes this endpoint. It accepts the client credentials plus a user id, verifies both, and returns a short-lived JWT the agent can use.
POST /auth/client-user-token| Field | Type | Required | Description |
|---|---|---|---|
| client_id | string | Yes | Your Sageion app_id. |
| client_secret | string | Yes | Your Sageion client secret. Keep this server-side only. |
| user_id | string | Yes | The user's id from your platform. Must be numeric. |
| session_id | string | No | Optional session identifier to correlate token usage. |
Response:
| Field | Type | Description |
|---|---|---|
| token | string | Short-lived JWT the agent uses for subsequent calls. |
| expires_in | number | Seconds until expiry â currently 3600. |
| scope | string[] | Actions authorized by the token. Currently: booking:read, booking:create, booking:update, booking:cancel. |
| user_id | string | Echo of the user_id the token was issued for. |
â ī¸ The token field must be encrypted
The token value you return must not be a plaintext JWT. Sageion rejects plaintext JWTs â the workflow engine will treat the response as a failure. The token must be hybrid-encrypted with the public key shown under Token Encryption Key and returned as a single string with the format: base64(rsa_wrapped_key).base64(nonce).base64(ciphertext||tag).
The reference implementations below show the full encryption routine. Note that the login server must refuse to start without the encryption key configured â a missing or invalid key should fail at deploy time, not at the first request.
Response contract â required fields
| Field | Type | Required | Why it matters |
|---|---|---|---|
| token | string | Yes | The encrypted JWT the agent attaches as a Bearer token. Missing or null â the agent cannot make authenticated calls. |
| expires_in | number | Yes | Seconds until expiry. If omitted, the agent cannot tell when to refresh the token. |
| scope | string[] | Yes | The list of actions this token authorizes. The agent checks this list before attempting operations. |
| user_id | string | Yes | Echo of the user_id the token was issued for. The agent uses it to verify the token is bound to the right user. |
Return this object at the top level with HTTP 200. On failure, return HTTP 401 (invalid client credentials) or HTTP 404 (user not found) with a plain JSON body â the agent treats non-2xx responses as refusals, not as retryable errors.
Reference implementation by language
Backend handler â Node.js
// routes/auth.js
const SAGEION_APP_ID = process.env.SAGEION_APP_ID;
const SAGEION_CLIENT_SECRET = process.env.SAGEION_CLIENT_SECRET;
router.post('/client-user-token', [
body('client_id').notEmpty(),
body('client_secret').notEmpty(),
body('user_id').notEmpty().isInt(),
body('session_id').optional().isString(),
], async (req, res) => {
const { client_id, client_secret, user_id, session_id } = req.body;
// 1. Verify client credentials
if (client_id !== SAGEION_APP_ID || client_secret !== SAGEION_CLIENT_SECRET) {
return res.status(401).json({ error: 'Invalid client credentials' });
}
// 2. Verify the user exists
const check = await pool.query('SELECT id FROM users WHERE id = $1', [user_id]);
if (check.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}
// 3. Issue a scoped, short-lived token
const scopes = [
'booking:read', 'booking:create', 'booking:update', 'booking:cancel',
];
const plaintextToken = generateToken(user_id, 'client@system', 'client', {
scope: scopes,
client_id,
session_id,
});
// 4. Encrypt before returning â Sageion rejects plaintext JWTs.
const encryptedToken = encryptToken(plaintextToken);
res.json({ token: encryptedToken, expires_in: 3600, scope: scopes, user_id });
});Calling it from your agent workflow (Node.js)
const axios = require('axios');
async function getAgentToken(userId) {
const { data } = await axios.post(
`${process.env.API_BASE_URL}/auth/client-user-token`,
{
client_id: process.env.SAGEION_APP_ID,
client_secret: process.env.SAGEION_CLIENT_SECRET,
user_id: String(userId),
}
);
return data.token; // use as Bearer token for agent-initiated calls
}2. OTP endpoints (/auth/send-otp, /auth/verify-otp)
Two endpoints back an OTP flow, useful when an action triggered from chat needs a second factor of confirmation â for example, cancelling a booking.
OTP is not your login
These endpoints verify one-off actions. They are separate from your main login flow and do not issue a session token.
2a. Send OTP â POST /auth/send-otp
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Email address the OTP is associated with. |
Generates a 6-digit OTP, stores it against the email, and expires it after 5 minutes. The reference implementation logs the OTP â plug in your own email provider for delivery.
Response contract â required fields
| Field | Type | Required | Why it matters |
|---|---|---|---|
| success | boolean | Yes | The workflow engine checks this to decide whether to proceed to the verification step. |
Return this object at the top level with HTTP 200. If sending fails (bad email, provider outage), return HTTP 400 or 500 â do not return 200 with success: false, because the workflow engine treats 2xx as authoritative.
Reference implementation by language â /send-otp
// routes/auth.js â send OTP
router.post('/send-otp', [
body('email').isEmail().normalizeEmail(),
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
const { email } = req.body;
const otp = Math.floor(100000 + Math.random() * 900000).toString();
const expiresAt = new Date(Date.now() + 5 * 60 * 1000); // 5 min
try {
await pool.query(
`INSERT INTO otps (email, otp, expires_at) VALUES ($1, $2, $3)
ON CONFLICT (email) DO UPDATE SET otp = $2, expires_at = $3`,
[email, otp, expiresAt]
);
// TODO: send via your email provider
console.log(`[OTP] Sent OTP ${otp} to ${email}`);
res.json({ success: true, message: 'OTP sent' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Server error' });
}
});2b. Verify OTP â POST /auth/verify-otp
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | The email the OTP was sent to. | |
| otp | string | Yes | The 6-digit code the user entered. |
On success, returns { success: true, user_id } so the workflow can continue with the verified identity. The OTP record is deleted after verification.
Response contract â required fields
| Field | Type | Required | Why it matters |
|---|---|---|---|
| success | boolean | Yes | The workflow engine checks this to allow the OTP-gated action to proceed. |
| user_id | string | Yes | The verified user's id. The workflow continues with this identity â omitting it breaks any downstream user-scoped call. |
Return this object at the top level with HTTP 200. On verification failure, return HTTP 400 with a plain JSON body.
user_id must be a string
JSON numbers lose leading zeros and can be represented inconsistently across languages (JavaScript numbers, Go int64, Python int). To keep the identity check reliable, always return user_id as a JSON string â for example "user_id": "12345" â even if your database column is an integer.
Reference implementation by language â /verify-otp
// routes/auth.js â verify OTP
router.post('/verify-otp', [
body('email').isEmail().normalizeEmail(),
body('otp').isLength({ min: 6, max: 6 }).matches(/^\d+$/),
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
const { email, otp } = req.body;
try {
const result = await pool.query(
'SELECT otp, expires_at FROM otps WHERE email = $1',
[email]
);
if (result.rows.length === 0) {
return res.status(400).json({ error: 'No OTP request found' });
}
const record = result.rows[0];
if (record.otp !== otp) {
return res.status(400).json({ error: 'Invalid OTP' });
}
if (new Date() > new Date(record.expires_at)) {
return res.status(400).json({ error: 'OTP expired' });
}
const userResult = await pool.query(
'SELECT id FROM users WHERE email = $1', [email]
);
if (userResult.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}
const userId = userResult.rows[0].id;
await pool.query('DELETE FROM otps WHERE email = $1', [email]);
res.json({
success: true,
message: 'OTP verified successfully',
user_id: userId.toString(),
});
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Server error' });
}
});â You're done with the base integration
Everything above the "Binding the AI agent to a user" section is what you need to get Sageion working. Everything from that section onward is additive â nothing there is required for the chat box to work.
Platform
The Sageion Admin Platform provides comprehensive tools for managing your chat applications, users, and system settings. Below is an overview of the key sections available in the Admin UI.
Global Level Settings
These settings apply across all applications within your tenant, providing centralized control over system-wide configurations.
đ Admin Access Required
Only users with ADMIN or MANAGER role have access to these settings. If you don't see these options, contact your system administrator.
Global Tenant Settings
The Global Tenant Settings page allows administrators to configure tenant-wide features that affect all applications under the tenant.
Enables email notifications at various useful events across all applications. This toggle controls whether email alerts are sent for key system events.
đ§ Available Notification Triggers
| Trigger | Description | Availability |
|---|---|---|
| FIRST MSG ON ANY APP | Triggers when the first message arrives on any app since admin went offline | All Plans |
| FIRST MSG ON EVERY APP | Triggers when the first message arrives on every app since admin went offline | đ ADVANCE Plan Only |
Configuration Options
Email notifications can be customized per event type. Configure which events trigger emails and the recipient list in the settings panel.
Plan Restriction
"FIRST MSG ON EVERY APP" is only available on the ADVANCE plan. Upgrade your plan to access this feature.
Invite Support User
Invite team members as support users with granular permission controls. This feature allows you to add users with specific roles and permissions to manage your applications.
đ Multi-Admin Required
The Invite Support User feature requires Multi-Admin to be enabled in Global Tenant Settings first. This ensures proper permission hierarchy and security.
đ¤ User Roles
| Role | Access Level | Primary Responsibilities |
|---|---|---|
| MANAGER | Full Access | Manage applications, settings, and users |
| DEVELOPER | Technical Access | API configuration, workflows, and technical settings |
| CUSTOMER_CARE_EXECUTIVE | Limited Access | All Chats and user management |
Role Assignment
Users can be assigned multiple roles. The combination of roles determines the user's overall permissions.
Whitelabel Domains
Configure custom domains for your applications to maintain brand consistency. This allows you to serve the Sageion chat interface from your own domain.
Available Features
- Add custom domain names for your applications
- SSL certificate management
- DNS configuration guidance
DNS Configuration Guide
To set up a custom domain:
- Add your domain in the Whitelabel Domains section
- Configure DNS records as instructed
- Wait for DNS propagation (24-48 hours)
- Verify the domain and enable SSL
â Setup Complete
Once configured, your chat interface will be served from your custom domain, providing a seamless brand experience for your users.
FAQ Chat & Lead Generation
The FAQ Chat & Lead Generation section provides powerful tools for building interactive FAQ trees, managing leads, and capturing visitor information through forms.
LeadGen & FAQ
This feature combines two powerful capabilities: Interactive FAQ/Q&A Trees and Lead Generation.
Two Modes
- FAQ/Q&A Tree Mode: Build hierarchical question-answer structures
- Lead Generation Mode: Capture leads at any node in the tree
đŗ FAQ Tree Builder
The Dynamic Tree Builder allows you to create structured FAQ content:
- Create hierarchical question-answer trees
- Add sub-questions and answers
- Attach lead generation forms at any node
- Enable/disable the FAQ bot content
â ī¸ At Least One Chatbot Required
You must have at least one chatbot enabled at all times. The system validates that either AI Chat, Live Agent, or FAQ Bot is active. You cannot disable all chatbots simultaneously.
đ¯ Lead Generation Management
Capture and manage leads from your FAQ forms and other sources:
- View all captured leads with timestamps and metadata
- Export leads to XLSX or CSV format
- Leads are automatically stored in the Admin Panel
- Connect to external servers via AI Agent workflows
| Lead Field | Description |
|---|---|
| Lead ID | Unique identifier for each lead |
| Timestamp | When the lead was captured |
| Lead Data | Form fields and user responses |
| Metadata | Additional context (source, page, etc.) |
đ Bot Forms & Post-Processing
Configure how forms behave and what happens after submission:
| Template Type | Description | Use Case |
|---|---|---|
| THANK_YOU | Shows appreciation message | Simple thank you response |
| GET_BACK_TO_YOU_SHORTLY | Informs about follow-up | Lead qualification |
Lead Storage Options
- Built-in Storage: Leads stored in Sageion Admin Panel under Lead Generation section
- External Integration: Send to external servers via orchestrated AI Agent workflows
đ§ Form Field Configuration
Each form can have multiple fields with the following properties:
| Field Property | Description | Example |
|---|---|---|
| Label | Display name | Email Address |
| Type | Field type | text, email, phone, etc. |
| Required | Whether field is mandatory | true/false |
| Placeholder | Hint text | Enter your email |
â Best Practice
Keep lead capture forms short and focused on essential information to maximize conversion rates.
đ Update Process
When updating LeadGen & FAQ settings:
- Make your changes to the FAQ tree or lead settings
- Click the 'Update' button at the bottom
- Review the confirmation modal (all clients will be rebooted)
- Confirm to apply changes
â ī¸ Client Reboot Warning
Updating LeadGen & FAQ settings will reboot all active clients to sync the new configuration.
â FAQ Chat & Lead Generation Overview Complete
The LeadGen & FAQ feature provides a complete solution for building interactive FAQ trees and capturing leads from your website visitors.
Live Agent
The Live Agent feature enables real-time human-to-human chat support, allowing you to interact directly with your website visitors and provide personalized assistance.
Live Agent Features
Configure all aspects of your Live Agent experience including enabling/disabling, user capacity, chat appearance, messaging, and updates.
Site Users represent the total number of unique visitors who can register and interact with your Live Agent. Each registered user consumes one slot from your capacity.
đ Understanding Your Capacity
| Metric | Description |
|---|---|
| Plan Limit | Base number of user slots included in your plan |
| Top-ups Added | Additional slots purchased through top-ups |
| Total Capacity | Plan Limit + Top-ups Added |
| Available Slots | Remaining slots available for new users |
- Progress bar shows remaining capacity percentage
- Low capacity warning appears when below 20%
- Critical warning appears when 0 slots remain
đ How Site Users Work
Each unique visitor who registers or starts a chat session consumes one user slot. Slots are not released until the user is explicitly removed or the session expires.
đĨ Top-Up Options
When you're running low on user slots, you can purchase additional capacity:
| Slots Added | Price | Cost Per Slot |
|---|---|---|
| +125 Slots | âš1,500 | ~âš12 per slot |
| +250 Slots | âš3,000 | ~âš12 per slot |
| +375 Slots | âš4,500 | ~âš12 per slot |
đĄ Pro Tip
Top-ups are added permanently to your total capacity. Consider purchasing larger packages for better value if you expect high user growth.
â Live Agent Overview Complete
The Live Agent feature provides real-time human chat support for your website visitors. Enable it to offer personalized assistance and improve customer satisfaction.
Monitor your Site Users capacity regularly and top up when needed to ensure you never run out of slots for new users.
AI Chat
The AI Chat feature provides intelligent conversational AI capabilities for your website, enabling automated customer support, lead qualification, and information retrieval using advanced language models.
AI Chat Features
Configure all aspects of your AI Chat experience including enabling/disabling, message credits, ingestion storage, data sources, and training.
The AI Agent bot provides automated conversational AI capabilities for your website visitors.
How to Enable
- Navigate to AI Chat settings from the sidebar
- Toggle the 'Enable AI Agent Bot' switch to ON
- All AI agent settings will appear below
- Configure your data sources and training
- Click 'Update AI Chat' to save changes
đ¤ What the AI Agent Can Do
- Answer customer questions 24/7
- Qualify leads through conversation
- Retrieve information from your knowledge base
- Escalate complex issues to human agents
â ī¸ At Least One Chatbot Required
You must have at least one chatbot enabled at all times. The system validates that either AI Chat, QnA (LeadGen) Bot, or Live Agent is active. You cannot disable all chatbots simultaneously.
â AI Chat Overview Complete
The AI Chat feature provides intelligent conversational AI for your website. Enable it to automate customer support, qualify leads, and provide 24/7 assistance.
Monitor your AI message credits and ingestion storage regularly. Top up when needed and retrain your AI Agent with fresh data to keep responses accurate and relevant.
All Chat
The All Chat feature provides a comprehensive real-time messaging interface for agents to communicate with site visitors, manage conversations, and provide support across all applications.
All Chat Features
The All Chat interface provides a complete messaging solution for support agents, including user management, real-time messaging, file sharing, and conversation history.
The All Chat interface is divided into two main sections: the left sidebar showing all users and the right panel displaying the active conversation.
đą Interface Layout
| Section | Description | Key Features |
|---|---|---|
| Left Sidebar | Displays all users across all applications | User list, online status, unread counts, app grouping |
| Right Panel | Shows the active conversation | Message history, typing indicator, message input, file upload |
- Users are grouped by application for easy navigation
- Each user shows their name, online status, and unread message count
- Click on a user to open the conversation
- The chat header displays the user's name and online status

đĄ Quick Navigation
Use the 'Back to Users' button in the chat header to return to the user list. The 'Refresh' button at the top reloads the entire user list.
â All Chat Overview Complete
The All Chat feature provides a complete real-time messaging solution for support agents. It includes user management, file sharing, message reactions.
Use the All Chat interface to manage all your support conversations in one place, across all applications and regions.
Agent & Servers
The Agent & Servers section provides comprehensive tools for configuring API connections, building multi-step workflows, and managing response templates for your chatbot applications.
Authentication Configure
Authentication Configure is where you connect your backend's authentication system to Sageion. Sageion uses these servers to obtain the access tokens it needs to call your APIs on behalf of an authenticated user â and, optionally, to send and verify one-time passwords (OTPs) for multi-factor login flows.
đ Who calls these servers?
Every authentication endpoint described here is called by the Sageion backend, never by the end user's browser. Your servers must accept requests from Sageion's infrastructure. They must not require any credentials beyond what is documented below.
The Primary Authentication server is your login server. It is called whenever Sageion needs to obtain a fresh access token for a user. The token your server returns is then used to authenticate every subsequent API call on that user's behalf, until it expires.
What Sageion sends you
When Sageion needs a token, it calls your login server with a JSON body containing four fields:
{
"client_id": "MyAppName",
"client_secret": "the-real-secret-your-server-validates",
"user_id": "36",
"session_id": "sess-abc-2"
}- client_id â an identifier for the app making the request. Sageion always sends your app name here.
- client_secret â the secret your server validates. This is the value you provided during setup.
- user_id â the ID of the user the token is being requested for.
- session_id â the session identifier. Sageion always sends this value. Your server may use it to scope the token to the current session, or ignore it if your tokens are not session-scoped.
What your server must return
On success, respond with HTTP 200 and a JSON body containing a token field:
{
"token": "<encrypted token string>"
}â ī¸ The token must be encrypted
The token you return must be encrypted with the public key shown under Token Encryption Key. Sageion will not accept a plaintext JWT â the token must be the hybrid-encrypted ciphertext, base64-encoded, in the format documented in the Token Encryption Key section.
Requirements on your endpoint
| Field | Requirement |
|---|---|
| HTTP method | POST |
| Content-Type | application/json |
| Authorization header | Must NOT be present. Sageion adds authentication for its own calls; this server is your starting point. |
| URL path | Plain path only â no query strings, no placeholders anywhere in the URL. |
| Response body | Must be JSON with a token field on 2xx. |
Error responses
If your server returns a non-2xx status, Sageion propagates your error message back to the user-facing system. Write the error messages you want end users to see â they are shown as-is.
| Status | When to use it | Example message |
|---|---|---|
| 401 | Credentials rejected, user not found, or session invalid | Invalid credentials, please try again |
| 400 | The request Sageion sent was malformed or missing required fields | Incorrect request, will be reported to Admin |
| 500 | Your login server errored or is temporarily unavailable | Auth Server is down, Please try again later |
đĄ One Primary Auth per app
You can configure exactly one Primary Authentication server per application. Every API that requires a token will use it.
API Configurations
API Configurations define the endpoints that your chatbot can call on behalf of the user. Each configuration describes the URL, method, request shape, and how the response should be turned into a chatbot message.
Define the API endpoint, method, headers, query parameters, and payload template.
Key Configuration Fields
| Field | Description | Example |
|---|---|---|
| API URL | Full endpoint URL with placeholders | https://api.example.com/bookings/{{ booking_id }} |
| HTTP Method | GET, POST, PUT, etc. | POST |
| Headers | Request headers (Authorization with {{ token }}) | Authorization: Bearer {{ token }} |
| Query Parameters | URL query parameters | limit={{ limit }}&page={{ page }} |
| Payload Template | JSON body with placeholders | {"room_id": "{{ room_id }}", "check_in": "{{ check_in }}" } |
âšī¸ GET requests have no payload
If your method is GET, the Payload Template is ignored. Leave it as {} and provide all inputs via the URL path or query parameters.
đ cURL Import
- Paste a cURL command to auto-generate the API configuration
- Parses URL, method, headers, query parameters, and payload
- Detects dynamic path variables (IDs, UUIDs)
- Requires you to either name each detected variable or mark it as 'Not a variable' before importing
- Supports multiple sample responses for different status codes
đĄ Pro Tip
Use the cURL importer to quickly set up APIs from existing curl commands. This saves time and reduces errors when configuring complex endpoints.
ChainApis
A Chain links several of your APIs into one branching workflow. Each API's response status decides which API runs next. Use Chains when a single skill needs more than one call to complete â for example, check availability, then book, then confirm.
The three parts of a chain
- Root API â the first call. It receives the visitor's input directly and its response decides what happens next.
- Branches â one per response status you want to handle. Each branch names the follow-up API to call when that status comes back.
- Mappings â for each branch, which fields from the previous response feed into the follow-up API's URL, query string, or payload.
Adding branches
Every API declares which statuses it returns in its own API Configuration. When you pick an API for a node, the editor automatically seeds one branch slot for each of those statuses. You just wire the ones you care about. You can't add a status the API doesn't already declare â if a status is missing, update the API Configuration first.
đĄ Statuses come from the API
A branch exists because your API can return that status. Adding an unconfigured status here would be a guess. Update the API Configuration to declare a new status, then come back â the branch slot will appear automatically.
How a chain runs
- The root API is called with the visitor's input.
- Its response status picks the matching branch.
- That branch's API is called, using the mappings you configured.
- The process repeats down the tree until a node has no branch for the status it returned.
â ī¸ A chain stops the moment a status has no branch
If an API returns 200 but you only wired a 202 branch, the chain stops there. Design branches for every status your API can meaningfully return, or accept the default fallback.
Response Settings
Response Settings allows you to manage response templates across all API configurations in one centralized location.
Centrally manage all response templates for your API configurations.
Template Features
- View and edit templates for each API config
- Create templates for multiple status codes
- Preview rendered messages
- Use Jinja syntax with field autocomplete
đ Centralized Management
Response Settings provides a single view of all templates across your API configurations. This makes it easy to maintain consistent messaging across your chatbot.
â Agent & Servers Overview Complete
The Agent & Servers section provides a complete toolkit for connecting your chatbot to backend services, building complex workflows, and managing user-facing responses.
Start by configuring authentication and your API endpoints, then build chains for complex workflows, and finally design user-friendly response templates to create a seamless user experience.
Visual Response Designer
The Visual Response Designer is a powerful no-code tool that lets you design exactly how your AI responses appear to users. Build stunning, interactive screens without writing a single line of code.
What is the Visual Response Designer?
The Visual Response Designer is a drag-and-drop interface that transforms raw API responses into beautiful, user-friendly messages. It's designed for product managers, support teams, and developers who want full control over their chat experience without writing code.
đĄ Why Use the Visual Response Designer?
- â No coding required â design visually, just like building a slide
- â See exactly what your users will see, in real-time
- â Transform data into tables, cards, lists, and styled text with one click
- â Perfect for customer support teams, product managers, and non-technical users
Key Concepts
Understanding these core concepts will help you get started quickly:
đ Screen
A Screen is what your users see in the chat. Each screen can display different information. You can create:
- Single Screen: All data appears on one screen (perfect for simple responses)
- Multiple Screens: Each data item appears on its own screen (great for lists, search results, or multi-item responses)
đ Template
A Template is the design of your response. It defines what information appears and how it's organized. Think of it like a slide design in PowerPoint â you design once, and it works for all your data.
đ Transformations
Transformations are visual enhancements you can apply to your design with one click:
- đ Table View â Show data in a clean, organized table
- đ Card View â Display each item as a beautiful card
- đ List View â Show items in a simple list format
- đ¨ Style Transformations â Highlight, bold, italicize, or underline text
Getting Started
Follow these steps to create your first visual response:
1
Step 1: Paste Your Sample Response
Copy a sample JSON response from your API and paste it into the 'Sample Response' area. This gives the designer an example of your data structure.
đĄ Tip
Use a real response from your API to see exactly how your data will appear. The designer automatically generates a starting template from your sample.
2
Step 2: Click 'Render Preview'
This generates a visual preview of your response. You'll see how your data looks and can start designing.
3
Step 3: Open the Visual Editor
Click 'Open Editor' to access the visual design interface. Here you can:
- Drag rows to reorder content
- Edit text directly inline
- Add custom messages
- Insert dynamic data fields
4
Step 4: Apply Transformations
Use the 'Start Wizard' button to transform your design:
- Structure â Convert to Table, Cards, or List view
- Media â Turn image URLs into actual pictures
- Styles â Apply colors, bold, italic, and alignment
5
Step 5: Save Your Design
Click 'Use Template' or 'Save Configuration' to save your visual design. It's now ready for your users!
The Visual Editor
The Visual Editor is where you design your responses. It's designed to be intuitive and powerful, like a slide editor:
đąī¸ Drag & Drop Reordering
Simply drag any row up or down to change the order of content. Your changes are reflected instantly in the preview.
âī¸ Inline Editing
Click the â icon on any row to edit its content directly. You can:
- Change text labels
- Add custom messages
- Insert dynamic data using the @ menu
â Add Buttons & Button Groups
Add interactive elements to your responses:
- Single Buttons â Perfect for simple actions like 'Book Now' or 'Learn More'
- Button Groups â Multiple buttons in a row for related actions
đĄ Pro Tip
Use Button Groups to offer users choices. Each button can trigger different actions, like 'View Details', 'Book Now', or 'Contact Support'.
The Transformation Wizard
The Transformation Wizard is your creative toolkit for enhancing responses. It walks you through three steps:
Change how your data is organized and displayed:
| Transformation | What It Does | Best For |
|---|---|---|
| đ Table View | Organizes data into a clean table with headers and rows | Comparing multiple items, structured data |
| đ Card View | Shows each item as a separate card with a title and details | Profiles, product listings, individual records |
| đ List View | Simple list format with each item on a new line | Quick overviews, short lists |
| đ JSON View | Shows the raw data structure | Debugging and technical reviews |
đĄ Card View Options
Card View can be displayed vertically (scrolling down) or horizontally (scrolling sideways). Choose the direction that best fits your content.
Single Screen vs Multiple Screens
The Visual Response Designer automatically detects your data structure and suggests the best layout:
| Layout Type | When It's Used | What Users See | Example |
|---|---|---|---|
| Single Screen | Your data has a single item or metadata with arrays | All information on one screen | A hotel booking confirmation with guest details |
| Multiple Screens | Your data has a list of items at the root or in an array | Each item appears on its own screen | A list of available rooms, each with its own screen |
đĄ How It Works
The designer analyzes your data structure automatically. If you have a list of items, you'll get multiple screens. If you have a single object, you'll get a single screen. You can always adjust the design manually.
Live Preview
The Visual Response Designer shows you exactly what your users will see, updated in real-time as you design:
- đī¸ See your changes instantly â no refresh needed
- đą Preview in Desktop or Mobile view
- đ See how your design looks with different data
- â Ensure everything looks perfect before saving
đĄ Pro Tip
Use the Desktop/Mobile toggle to test how your design looks on different devices. This ensures a great experience for all users.
Saving & Deployment
Once your design is ready, saving it is simple:
1
Review Your Design
Check the preview to ensure everything looks perfect.
2
Click 'Use Template'
This saves your design to the configuration. If you're in the standalone tool, click 'Save Configuration'.
3
Deploy to Users
Your visual design is now live! Users will see the beautiful, professional responses you've created.
â ī¸ Important
When you save a design, all active clients (users) will be updated automatically to see the new response format.
Best Practices
Follow these tips to create the best user experience:
- đĄ Start simple â begin with a basic design and add complexity gradually
- đą Test on mobile â always preview your design in mobile view
- đ¯ Be consistent â use similar styles across all responses for brand coherence
- đ Use Card View for multi-item responses to improve readability
- đ¨ Apply styles sparingly â highlight only what's truly important
- đ Use buttons to guide users to the next action
â Visual Response Designer Overview Complete
The Visual Response Designer is a no-code tool that empowers you to create beautiful, professional responses without writing code. Whether you're a product manager, support lead, or developer, you can design exactly what users see in the chat.
Start with your sample data, design visually, and deploy to users instantly. No coding required.
Congratulations! Your integration should now be successful!
Your users can now sign up and seamlessly chat with the Admin Team, enabling two-way communication.
Please contact our Support Team if you encounter any issues. Thank you!