Authenticated Web Integration

Complete guide to integrate the Caramelo AI chatbot into intranets and authenticated areas using the Server-to-Server flow.

Authenticated Flow

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:

  1. 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).
  2. 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:

ItemDescriptionExample
Project IDYour project ID on Caramelo AIp_xyz123
Secret TokenAn authenticated_flow key generated in the dashboardsk_live_abc...

⚠️ Warning: The secret_token must 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

FieldTypeRequiredDescription
secret_tokenstringYour secret key generated in the dashboard.
external_customer_idstringUnique, immutable identifier for the user in your system.
namestringUser name for personalization and reports.
emailstringUser email.
langstringPreferred 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 the index.js used 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.