Overview
This guide describes the steps required to securely implement the Caramelo AI chat widget within your intranet or authenticated area, using the Server-to-Server authenticated flow.
This flow ensures that only users authenticated in your system can access the chatbot and that conversation history is maintained securely, tied to the user.
How It Works
The process consists of two main steps:
- Backend (Server-to-Server): Your server communicates with the Caramelo AI API by sending the authenticated user’s data and a secret token. Our API returns a temporary connection token (
real_time_access_token). - Frontend: Your server injects this temporary token into the page’s HTML. The Caramelo AI SDK will use this token to establish a secure chatbot connection.
┌──────────────┐ POST /intranet-auth ┌──────────────────┐
│ Your Backend │ ──────────────────────────────► │ Caramelo AI API │
│ │ ◄────────────────────────────── │ │
│ │ real_time_access_token │ │
└──────┬───────┘ └──────────────────┘
│
│ Injects token into HTML
▼
┌──────────────┐
│ Frontend │ ──► SDK authenticated.js ──► Secure WebSocket
│ (Browser) │
└──────────────┘
Prerequisites
Before you begin, make sure you have:
| Item | Description | Example |
|---|---|---|
| Project ID | Your project ID on Caramelo AI | p_xyz123 |
| Secret Token | An authenticated_flow key generated in the dashboard | sk_live_abc... |
⚠️ Warning: The
secret_tokenmust be kept secret on your backend and NEVER exposed on the frontend.
Step 1: Backend Authentication (Server-to-Server)
When the user accesses the chat page, your server must make a POST request to the Caramelo AI API before rendering the page.
Endpoint
POST https://api.carameloai.com/api/chatbox/project/{project_id}/intranet-auth
Replace
{project_id}with your project ID.
Headers
{
"Content-Type": "application/json"
}
Body (JSON)
{
"secret_token": "YOUR_SECRET_TOKEN",
"external_customer_id": "12345",
"name": "John Doe",
"email": "john@email.com",
"lang": "en"
}
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
secret_token | string | ✅ | Your secret key generated in the dashboard. |
external_customer_id | string | ✅ | Unique, immutable identifier for the user in your system. |
name | string | — | User name for personalization and reports. |
email | string | — | User email. |
lang | string | — | Preferred language (e.g., pt, en, es). |
Successful Response (200 OK)
{
"real_time_access_token": "eyJhbGciOiJIUzI1NiIsIn...",
"customer_id": "c_...",
"chat": { ... },
"chatbot": { ... }
}
The value you will need for the next step is real_time_access_token.
Step 2: Frontend Configuration
With the real_time_access_token returned by the API, your server must inject it as secure_connection_token into the HTML of the page where the chatbot will be displayed.
Add the following code to your page (ideally before the closing </body> tag):
<!-- 1. Chatbot Configuration with the Secure Token -->
<script>
var carameloaiChatbot = {
secure_connection_token: "INSERT_REAL_TIME_ACCESS_TOKEN_HERE",
project_id: "INSERT_PROJECT_ID_HERE"
};
</script>
<!-- 2. SDK Initialization (Authenticated Mode) -->
<script src="https://static.carameloai.com/sdk/latest/authenticated.js"></script>
⚠️ Important: The file loaded in step 2 is
authenticated.js, which is different from theindex.jsused in public flows. Do not mix the two.
Full Example (Node.js / Express)
Here is a simplified example of how your backend could generate the page:
const PROJECT_ID = "p_xyz123";
const SECRET_TOKEN = process.env.CARAMELO_SECRET_TOKEN;
app.get('/my-intranet', async (req, res) => {
// 1. Get data from the already logged-in user
const user = req.user;
// 2. Call the Caramelo API
const response = await fetch(
`https://api.carameloai.com/api/chatbox/project/${PROJECT_ID}/intranet-auth`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret_token: SECRET_TOKEN,
external_customer_id: user.id,
name: user.name,
email: user.email
})
}
);
const data = await response.json();
const secureToken = data.real_time_access_token;
// 3. Render the HTML with the injected token
res.send(`
<html>
<head><title>My Intranet</title></head>
<body>
<h1>Welcome, ${user.name}</h1>
<!-- Backend-generated token injection -->
<script>
var carameloaiChatbot = {
secure_connection_token: "${secureToken}",
project_id: "${PROJECT_ID}"
};
</script>
<script src="https://static.carameloai.com/sdk/latest/authenticated.js"></script>
</body>
</html>
`);
});
FAQ
Does the token expire?
Yes, the real_time_access_token is a temporary token used to establish the WebSocket connection. Every time the page is reloaded, a new token must be generated by your backend.
Can I use the public script (index.js)?
No. For authenticated connections with secure_connection_token, you must use the authenticated.js script instead of index.js.
What happens if the token is intercepted?
The token is short-lived and tied to a specific session. Even if intercepted, it cannot be reused after expiration or for a different user.
Does it work with SSR (Server-Side Rendering)?
Yes. The flow was designed for SSR — the token is generated on the backend and injected into the HTML before sending it to the browser.